Archivo de la categoría: Artículos Técnicos

Creando una VM de Azure desde línea de comandos (Primera parte)

Hoy tenía la necesidad de configurar una máquina virtual de Azure. Podía haber optado por la manera simple, que es conectarme al portal y configurarla, pero ya que tenía el SDK de Azure instalado, he decidido probar a ver cuanto puedo hacer desde línea de comandos.

Creando un grupo de afinidad y una storage account

El primer paso es crear un grupo de afinidad que es, básicamente, una sub-región donde podemos tener varios servicios. En mi caso lo configuraremos en la región del oeste de Europa:

New-AzureAffinityGroup -Name Sample -Location "West Europe"

El siguiente paso es crear una storage account, una cuenta en la que almacenaremos la máquina virtual, en el grupo de afinidad que hemos creado antes

New-AzureStorageAccount -StorageAccountName "NAME" -Label "sqlServer" -AffinityGroup "Sample"

Una vez la hemos creado, la podemos almacenar en una variable para su posterior uso:

$storage = (Get-AzureStorageAccount | where {$_.StorageAccountName -Contains "NAME"})

Finalmente fijamos esta cuenta de almacenamiento como la cuenta por defecto de nuestra suscripción.

Para ello necesitamos el nombre de nuestra suscripción, que lo podemos obtener con este comando:

Get-AzureSubscription

Con el nombre de la suscripción podemos fijar la cuenta de storage actual, usando la variable obtenida anteriormente:

Set-AzureSubscription -SubscriptionName $subscription.SubscriptionName -CurrentStorageAccountName $storage.StorageAccountName

Buscando la máquina que necesitamos desplegar

El primer paso es conseguir la máquina virtual que queremos agregar, para lo cual podemos filtrar y seleccionar solamente las máquinas que cumplen ciertos requisitos:

Get-AzureVMImage | where {$_.Label -match "SQL Server 2014"} | Select Label

Una vez que hemos seleccionado una imagen base, la podemos asignar a una variable para su posterior uso:

$vm = (Get-AzureVMImage | where {$_.Label -match "SQL Server 2014"})[6]

Finalmente podemos crear nuestra máquina virtual, con los comandos New-AzureVMConfig, Add-AzureProvisioningConfig y New-AzureVM:

New-AzureVMConfig -Name "VM-NAME" -InstanceSize Small -ImageName $vm.ImageName | Add-AzureProvisioningConfig -Windows -AdminUsername "USER" -Password "PASSWORD" | New-AzureVM -ServiceName 'SERVICENAME' -AffinityGroup "Sample"

Si todo ha ido bien, podremos ver que, tras ejecutar el siguiente comando:

Get-AzureVM 

Se muestra nuestra máquina virtual en estado de “Provisioning”.

Conclusiones

Ha sido cuanto menos curioso (y más difícil de lo que imaginaba en un principio) no solo por la sintaxis de los comandos, sino porque a veces no somos conscientes de todos los procesos que se ejecutan cuando creamos una máquina virtual.

El hecho de que esto sea un script, es que lo podemos meter en un bucle for y crear 20-50-100 máquinas de la misma manera, según nuestras necesidades.

En el siguiente artículo veremos qué podemos hacer una vez que el provisionamiento está completo. Nos podremos conectar por Powershell como si de SSH se tratara? Podremos descargar el perfil de RDP desde la línea de comandos? La respuesta a esta y más preguntas en el próximo artículo de la serie.

Anuncios

8 cosas aprendidas de Android en el Codemotion 2014

En el pasado Codemotion 2014 pude asistir a varias charlas relacionadas con el desarrollo de aplicaciones para Android, en las que pude aprender y recordar algunos conceptos y herramientas que resumo en este pequeño artículo:

1. Model-View-Presenter

Fuente: Wikipedia DE

Fuente: Wikipedia DE

El patrón Model View Presenter es muy similar a Model View ViewModel en la base, ya que tanto el ViewModel como el Presenter notifican a la vista de los cambios, y reciben los comandos de la misma.

En el caso de Android, se propone el uso de Interfaces entre Presenter y la Vista, de manera que trabajamos, con clases abstractas, consiguiendo cierta independencia con las implementaciones.

2. Arquitecturas hexagonales

El uso de las clases abstractas con los MVP es lo que deriva en una arquitectura hexagonal, en la que mediante puertos (que es como se denominan estas interfaces) nuestra lógica de negocio se comunica con las diferentes abstracciones de la vista y diferentes servicios como comunicaciones o almacenamiento.

Fuente: VICTOR SAVKIN

Fuente: VICTOR SAVKIN

En el caso concreto de Android, la lógica de negocio puede estar completamente aislada en un módulo Java puro, lo que da una mayor independencia de la plataforma.

3. Documentación de calidad mantenida por la comunidad

android-guides

Los manuales de android guides, creados por los chicos de codepath, contienen (a fecha de hoy) más de 100 artículos con guías prácticas de desarrollo, cubriendo temas como fragments, persistencia, o guías completas como cómo empezar con gradle. Resultan verdaderamente interesantes y desde luego es un lugar a añadir a mi lista de favoritos.

4. Motores de Inyección de dependencias

De la misma manera que tenemos ninject en .NET o bien podemos crear nuestro propio motor, para Android tenemos Dagger (para inyección de dependencias en general) y Butterknife (para inyectar vistas), que nos permiten gestionar las dependencias de nuestros objetos (para implementar una arquitectura hexagonal como la que hemos definido anteriormente, por ejemplo).

5. Bases de datos y almacenamiento

url

En función de las necesidades que tengamos, hay dos proyectos que deberíamos tener en cuenta:

  • SugarORM, permite tener una base de datos local de manera extremadamente simple y manejable.
  • ORMLite compatible con cualquier proyecto de Java y permite una mayor personalización y estructuras un poco más complejas, además de estar más extendido en la comunidad.

Además, podemos o bien utilizar la clase ContentProvider para almacenar datos, o bien usar los adaptadores propios del sistema operativo, aunque se recomiendan las dos opciones anteriores.

Web: SugarORM (no confundir con SugarCRM): http://satyan.github.io/sugar/
Web: ORMLite: http://ormlite.com/

6. Testing

Para desarrollo Android tenemos muchas herramientas para hacer testing, desde JUnit que nos permite además de código Java estándar probar código específico para la plataforma, pasando por Mockito para crear artefactos para nuestros tests, y acabando con Espresso, para probar la UI de nuestra aplicación.

7. Programación reactiva

La programación reactiva o Reactive Programming es un paradigma que se basa en el flujo de datos, actualizando la visualización de los mismos a través del envío y recepción de mensajes. Es un tema verdaderamente interesante, ya que mezcla conceptos de programación funcional con patrones de lenguajes orientados a objetos como observer.

8. Otros lenguajes

Uno de los puntos fuertes de la JVM es la capacidad para ejecutar otros lenguajes más allá de Java, de esta manera podemos usar lenguajes como Kotlin (creado por Jetbrains), Groovy o incluso Clojure para hacer aplicaciones Android. El soporte para otros lenguajes es algo que está en proceso, pero que podemos tener en cuenta (Android Studio se lleva bastante bien con Kotlin, por ejemplo). Si nos vamos fuera de la JVM tenemos opciones como Xamarin que nos permite desarrollar apps para Android usando C#.

Conclusiones

Esta lista es solamente un resumen de varias charlas y conversaciones tenidas durante el evento. El ecosistema Android es muy interesante, no solo por todas las herramientas y técnicas disponibles, que una vez aplicadas se pueden llevar a otras plataformas, sino además por la comunidad que tiene, no solamente Android sino el lenguaje Java y los lenguajes basados en la JVM.

Nos vemos en la siguiente, aquí te dejo un recopilación de todas las charlas del Codemotion: https://docs.google.com/spreadsheets/d/14ZjJQ_VeT8mKmO8MANA1Os5zwRA3Pu_rpFdfyFtBZ4A/edit#gid=0

Resumen de atajos de teclado de Visual Studio

Una de las sesiones que me resultaron más interesantes en el pasado TechEd 2014 fue la de Tips and Tricks de Visual Studio con Tarek Madkur.

En ella, comentaba un montón de atajos de teclado que nos proporciona Visual Studio para mejorar nuestra productividad. En este artículo resumo brevemente las que más me han llamado la atención:

Ctrl + Q: Quick Launch

Este menú nos permite acceder, desde el teclado, a todas las ventanas auxiliares, opciones de configuración y elementos del menú del IDE. Ventanas como por ejemplo el “Package Manager Console” de Nuget, o ventanas como el Test Explorer, sin tener que estar buceando por las opciones del IDE.

Ctrl + K, X: Insertar snippet

Una herramienta muy útil cuando queremos reutilizar trozos de código llamados snipets. Este atajo nos muestra la lista de snipets instalados en nuestro sistema, y nos permite insertarlos de manera inmediata.

Alt + Shift + Enter: Pantalla completa

La pantalla completa es una vista que nos permite centrarnos en una (o varias) secciones de código, o cuando queremos mostrar código a alguien (por ejemplo, en una charla).

Ctrl + F4: Cerrar documento

Nos permite cerrar los documentos abiertos dentro del entorno de visual studio.

Shift + Esc: Ocultar ventanas

Nos permite cerrar otras ventanas como Output o Search Results, sin que ello afecte al layout actual.

Ctrl + Alt + O: Convertir en documento normal

Convierte un documento cargado en modo “preview” (el que se activa cuando hacemos click en un documento o cuando estamos navegando usando F12) en un documento normal.

Alt + F12: Peak navigation

El comando F12 nos permite navegar a la definición de un método o una clase, pero podemos perder el contexto, así que con esta opción podemos mantener el contexto y poder navegar a la definición. Lo más curioso es que podemos, dentro del menú de Peak navigation, continuar navegando

Extra! Más atajos de teclado!

El ilustre Gorka Madariaga (@Gk_8) aporta estos tres atajos:

Ctrl+C

En una linea sin seleccionar nada te la copia entera, idem para Ctrl+X o Ctrl+V (te la pega completa en la linea de arriba).

Ctrl+K, C

Comenta la linea en la que estas entera si no seleccionas nada o lo que tengas seleccionado, Ctrl+K, U hace lo inverso del anterior.

Ctrl+K, D

Para dar formato a todo el archivo o a lo que tengas seleccionado.

Conclusiones

Esta es una lista bastante corta de atajos de teclado, Visual Studio cuenta con una opción en el menú para poder listar todos los atajos, las opciones a las que están asignados, y asignarnos nuestros propios atajos (Por ejemplo, yo tengo configurado Ctrl + < para ejecutar mis test de Javascript)

Más información

Si quieres ver estas y más, te recomiendo la charla de Tarek Madkour en el TechEd 2014: https://channel9.msdn.com/Events/TechEd/Europe/2014/DEV-B348

Adding multiple languages to a Windows Store app with Javascript and Angular

Leer este artículo en castellano aqui

Last thursday I could attend a debate organized by MSCoders Madrid user group, related with localization of apps in a web enfironment.

After the event I got interested in frontend localization with Javascript. As Karmacracy for Windows is a Javascript app, I decided to do some experimentation on localizing the user interface in the context of a Windows Store app, to be able to distribute it for other markets.

Detecting the system language

For a Windows Store app the first thing to do is to detect the sustem language. This can be archieved with the following piece of code:

var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
var language = culture.substr(0, 2);

The culture is the language that is currently being used for the UI, in culture format. For example for Spanish of Spain would be es-ES, for US English would be en-US, and for British English would be en-GB. To be able to change this order and deploy our app, we must go to the control panel:

Captura de pantalla 2014-09-15 00.29.43

In this example we only need the language, not the culture, so we are going to get a substring of the culture getting en, es, de, etc.

Adding angular-translate

Angular-translate is a module that allows us to define key-value pairs for each language and perform the translation according to the configuration. For installing it, if we don’t use a package manager such as bower, we must download the last package from github and add it to our project.

Once installed, we must add it to the configuration of our app, in the section we define external modules (in this case the module is pascalprechtr.translate).

var karmacracyApp = angular.module('karmacracyApp', [
    'ngRoute',
    'karmacracyControllers',
    'pascalprecht.translate'
]);

Finally, we configure the different languages by using the code we defined previously for getting the OS display language:

karmacracyApp.config(['$translateProvider', function ($translateProvider) {
    $translateProvider.translations('en', {
        'LOGIN': 'Log in',
        'LOGIN_USERNAME': 'User name',
        'LOGIN_PASSWORD': 'Password'
    });

    $translateProvider.translations('es', {
        'LOGIN': 'Inicia sesión',
        'LOGIN_USERNAME': 'Nombre de usuario',
        'LOGIN_PASSWORD': 'Contraseña'
    });

    var culture = Windows.System.UserProfile.GlobalizationPreferences.languages[0];
    var language = culture.substr(0, 2);

     $translateProvider.preferredLanguage(language).fallbackLanguage('en');
}]);

Also, in case the current language is not available, we set English by default

#Usage

For accessing our keys we don’t need any aditional configuration on our controllers, we just need to modify our views so they can access the localized information

<span class="loginMessage">{{ 'LOGIN' | translate }}</span>

If the language is set to English or other language not controlled, the result will be the following:

en

If the language is set to spanish, the result will be the following:

es

As it shows, is an easy way to localize our javascript apps for the Windows Store.

Recap and next steps

Angular-translate provides a simple way of localizing texts in our views and Windows provides the information we need for setting the current language of an app.

As an aditional step, we may try to localize winjs controls such as buttons, which work in a very different way. Angular-translate also supports loading the translations from a json files, an option that may be useful if we want to distribute those files for translation by 3rd parties.

Links

Creando un motor de inyección de dependencias con C#

Read this article in English: Creating a Dependency Injection in C#

De acuerdo con la Wikipedia, la inyección de dependencias es un patrón de diseño de software que nos permite seguir el principio de inversión de dependencias mediante inversión de control, es decir, definir las dependencias de una clase desde fuera de la misma. En el caso de C# tenemos a nuestra disposición varios proyectos que generan todas las dependencias necesarias para nuestros objetos. Uno de estos es Ninject, un motor open-source con una sintaxis simple y plugins para ASP.net MVC y SignalR.

En este artículo veremos cómo funciona un motor de inyección de dependencias creando uno propio, basado en la sintaxis y la filosofía de Ninject.

Introducción

La inyección de dependencias nos ayuda a separar las responsabilidades entre las diferentes capas de nuestro código, así como mejorar la encapsulación y la facilidad de crear pruebas en nuestro código. Comencemos por un ejemplo simple, una lista de notas que nos permiten agregar una nota y guardarla llamando a _dataStorage, un objeto inicializado en el constructor:

public class NoteList
{
    private DataStorage _dataStorage;
    public NoteList()
    {
        _dataStorage = new DataStorage();
    }
    public void Add(string note)
    {
        if (string.IsNullOrEmpty(note))
        {
            throw new ArgumentException("Note cannot be empty");
        }

        _dataStorage.Save(note);
    }
}

DataStorage es una clase que escribe el contenido de una nota en disco, y que tiene el siguiente código para el método Save:

internal void Save(string note)
{
    using (StreamWriter writer = new StreamWriter("db.txt"))
    {
        writer.WriteLine(note);   
    }
}

El código de test se muestra a continuación:

//Arrange
var noteList = new NoteList();
var noteText = "myCustomNote";

//Act
noteList.Add(noteText);

//Assert
using (StreamReader reader = new StreamReader("db.txt"))
{
    var all = reader.ReadToEnd();
    Assert.IsTrue(all.Contains(noteText));
}

Como se puede ver, generamos un acoplamiento con DataStorage, esto significa que no podemos probar NoteList a menos que también probemos el comportamiento de DataStorage.

Eliminando el acoplamiento

El primer cambio que podemos hacer es abstraer DataStorage en una interfaz llamada IDataStorage. Seguidamente pasamos dicha interfaz como argumento en el constructor, en vez de inicializarla dentro de nuestra clase:

...
private IDataStorage _dataStorage;
public NoteList(IDataStorage dataStorage)
{
    _dataStorage = dataStorage;
}
...

El código de test cambia también, ya que pasamos a definir las dependencias fuera de la clase:

...
var dataStorage = new DataStorage();
var noteList = new NoteList(dataStorage);
var noteText = "myCustomNote";
...

Construyendo nuestro inyector

Una vez que tenemos una clase que recibe los parámetros como argumentos. Estos parámetros deben ser definidos e inicializados manualmente antes de llamar a nuestro constructor, con lo cual, el primer paso es generar dichos parámetros solicitando un tipo específico a nuestro Iniector. La primera versión es una clase estática con dos métodos y un diccionario interno para almacenar los mapeos, que tiene este aspecto:

private static Dictionary<Type, object> mappings
    = new Dictionary<Type, object>(); 

public static T Get<T>()
{
    return (T)mappings[typeof(T)];
}

public static void Map<T>(object o)
{
    mappings.Add(typeof(T), o);
}

Ahora podemos solicitar un objeto para la interfaz de nuestro test:

Injector.Map<IDataStorage>(new DataStorage());
var dataStorage = Injector.Get<IDataStorage>();

Este código presenta un problema, y es que siempre devolveremos el mismo objeto, y seguimos especificando el inyector en el constructor. Sería mucho más sencillo si el inyector devolviera una nueva copia de nuestro objeto, y si adicionalmente pudiéramos pedir nuestro objeto directamente desde el inyector:

Injector.Map<IDataStorage>(new DataStorage());
var noteList = Injector.Get<NoteList>();

Para poder llegar a estos resultados necesitamos una serie de mejoras importantes en nuestro inyector. El primer paso consiste en dividir el método Get en un método no genérico, de tal manera que podamos realizar llamadas recursivas como veremos más adelante:

public static T Get<T>()
{
    var type = typeof(T);
    return (T)Get(type);
}

El segundo paso consiste en cambiar la manera de almacenar los objetos, ya que en vez de una instancia, almacenaremos un tipo. De esta manera cambiamos el método Map para asegurarnos que no estamos almacenando un objeto específico, y que el tipo a almacenar hereda o implementa el tipo que se usará de clave:

public static void Map<T, V>() where V : T
{
    mappings.Add(typeof(T), typeof(V));
}

Finalmente, cambiamos nuestro método Get para invocar al constructor del tipo requerido, tras algunas comprobaciones adicionales:

private static object Get(Type type)
{
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();

    List<object> resolvedParameters = new List<object>();

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

    return constructor.Invoke(resolvedParameters.ToArray());
}

Veamos este código paso a paso: En primer lugar se resuelve el tipo, es decir, se comprueba si hay algún mapping disponible para el tipo especificado, en caso contrario se devuelve el mismo tipo:

private static Type ResolveType(Type type)
{
    if (mappings.Keys.Contains(type))
    {
        return mappings[type];
    }

    return type;
}

Una vez nos hemos asegurado de estar usando el tipo de dato correcto, el siguiente paso es recuperar el constructor, y su lista de parámetros (si existe).

...
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();
...

Si el constructor tiene parámetros, para cada uno de ellos se intentará resolver (es decir, se repetirá el proceso de manera recursiva), y si la resolución tiene éxito, se agregará a una lista de parámetros resueltos. En este caso el orden es muy importante ya que debe coincidir con el orden en el que se especifican los parámetros en el constructor**.

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

Finalmente se invoca el constructor con la lista de parámetros y se devuelve el objeto que se acaba de crear.

    return constructor.Invoke(resolvedParameters.ToArray());

La sintaxis final para obtener un nuevo objeto de nuestro inyector de dependencias es la siguiente:

Injector.Map<IDataStorage, DataStorage>();
var noteList = Injector.Get<NoteList>();

El resultado es una manera muy conveniente de generar un objeto sin preocuparnos de sus dependencias, que pueden estar definidas a un nivel mucho mayor.

Resumen

La inyección de dependencias no es un término oscuro ni mucho menos, nos permite crear arquitecturas desacopladas, y motores como el que acabamos de crear nos permiten crear la infraestructura necesaria a un nivel más alto, con lo cual el resto de las clases pueden tener solamente la lógica relacionada con su propio comportamiento (principio de responsabilidad simple) con un conjunto mínimo de dependencias. Por otro lado no es una pieza de software muy complicada, aunque en este caso es un ejemplo y el conjunto de casos cubiertos es mínimo.

Finalmente, las características de C# nos permiten hacer algo de metaprogramación al obtener tipos y parámetros de una función en tiempo de ejecución, así como crear objetos de manera dinámica, lo cual no está mal para un lenguaje fuertemente tipado. Sería interesante comprobar cómo podríamos crear una versión de este inyector en un entorno más dinámico y débilmente tipado.

Descarga el código!

Kata UpperCounter con Software Craftsmanship Madrid

El pasado martes 5 de agosto tuve la oportunidad de acudir a mi primer meetup de Software Craftsmanship Madrid, en el que se celebaba un coding dojo facilitado por Carlos Ble @carlosble. El objetivo de la sesión era hacer uso de un patrón diseñado por Robert “Uncle Bob” Martin llamado “Transformation Priority Premise” que nos lleva a una programación más genérica y funcional.

Tras sentarnos por parejas y escoger el entorno y el lenguaje de programación (En mi caso, C# con Visual Studio 2013 y XUnit como motor de pruebas) se desveló el objetivo de la kata:

Dada una cadena, devolver, en forma de array, las posiciones de dicha cadena cuyos caracteres sean la letra mayúscula

Ejemplos:
– A: {0}
– bA: {1}
– aBcdE: {1, 4}

Primera iteración, sin restricciones

Para esta primera iteración no teníamos ninguna limitación más allá de intentar resolver la kata. El resultado es el que se muestra en el vídeo:

El código completo, tanto del test como de la implementación se puede ver a continuación:

El enfoque es iterativo, utilizando un bucle para recorrer los caracteres de la cadena y la comprobación es bastante artesanal (a mejorar en la segunda iteración) y además, como teníamos tiempo, pudimos probar las Theories de XUnit, que nos permiten utilizar, en el mismo test, diferentes conjuntos de entrada y esperar diferentes resultados.

Segunda iteración, con restricciones

En esta segunda iteración teníamos una limitación importante: No podíamos asignar variables, ni modificar valores existentes. Esto nos deja sin la posibilidad de usar bucles (ya que vamos actualizando la posición del iterador) y forzando nuestro código a que sea más funcional. El resultado es el que se muestra:

El código completo es el siguiente, con el que intentamos seguir a rajatabla la indicación de no asignar o modificar los valores de las variables. En este caso el tiempo no permitió pasar de unos pocos test, pero se aprecia una diferencia notable por una parte en el test y por otra en el código de implementación:

Como nota adicional, gracias a @DanielRoz0 que me ha estado ayudando con la edición del vídeo, se pudo simplificar la comparación de una letra con su correspondiente mayúscula mediante el uso de la función char.IsUpper(source, index).

Información y enlaces:

Creating a Dependency Injection Engine with C#

According to the Wikipedia, dependency injection is a software design pattern that implements inversion of control and allows a program design to follow the dependency inversion principle. This patttern is implemented in C# with engines that generate all the required dependencies for our objects like Ninject, an open-source engine with a simple syntax and plugins for ASP.net MVC and SignalR.

In this article, we will see how does a dependency injection engine works by creating our own, based on Ninject’s syntax and philosophy.

Introduction

Dependency injection helps us to separate the concerns between the different layers of our code, and improve the encapsulation and testability of our code. Let’s start with a simple code, a list of notes that allows us to add a note, and saves it by calling _dataStorage, an object initialized in the constructor:

public class NoteList
{
    private DataStorage _dataStorage;
    public NoteList()
    {
        _dataStorage = new DataStorage();
    }
    public void Add(string note)
    {
        if (string.IsNullOrEmpty(note))
        {
            throw new ArgumentException("Note cannot be empty");
        }

        _dataStorage.Save(note);
    }
}

DataStorage is a class that writes the content of the note to disk, and has the following code for the Save method:

internal void Save(string note)
{
    using (StreamWriter writer = new StreamWriter("db.txt"))
    {
        writer.WriteLine(note);   
    }
}

The test code is the following:

//Arrange
var noteList = new NoteList();
var noteText = "myCustomNote";

//Act
noteList.Add(noteText);

//Assert
using (StreamReader reader = new StreamReader("db.txt"))
{
    var all = reader.ReadToEnd();
    Assert.IsTrue(all.Contains(noteText));
}

As we can see, we are generating a dependency on DataStorage (they are coupled), so this means that we cannot test NoteList unless we also test the behavior of DataStorage.

Removing coupling

The first thing we can do is to abstract DataStorage in an interface called IDataStorage. The following step is passing it as an argument, instead of initializing on the constructor:

...
private IDataStorage _dataStorage;
public NoteList(IDataStorage dataStorage)
{
    _dataStorage = dataStorage;
}
...

The test code also changes, so we define the dependencies from outside the class:

...
var dataStorage = new DataStorage();
var noteList = new NoteList(dataStorage);
var noteText = "myCustomNote";
...

Building our injector

Now we have a class that receives the parameters as arguments. These parameters must be defined and initialized manually before calling our constructor, so the first step is generating the parameters by asking our Injector for a specific type. The first version of our injector is a static class with two methods and an internal dictionary to hold the mappings, and it looks like this:

private static Dictionary<Type, object> mappings
    = new Dictionary<Type, object>(); 

public static T Get<T>()
{
    return (T)mappings[typeof(T)];
}

public static void Map<T>(object o)
{
    mappings.Add(typeof(T), o);
}

Now we can request an object for the interface in our test:

Injector.Map<IDataStorage>(new DataStorage());
var dataStorage = Injector.Get<IDataStorage>();

This code has an issue, that is that we always return the same object, and we are still specifying the injector in the constructor. It would be easier if the injector returns a new copy of the object and if we could also request our object directly from the injector:

Injector.Map<IDataStorage>(new DataStorage());
var noteList = Injector.Get<NoteList>();

For having these results we need to do some heavy improvements to our Injector. The first thing we are going to do is to divide the Get method into a non-generic one, so we can use recursion someway later:

public static T Get<T>()
{
    var type = typeof(T);
    return (T)Get(type);
}

The second thing we are going to do, instead of storing the object in our dictionary, is store the type, so we change also the Map method, this way we make sure of not storing a specific object:

public static void Map<T, V>() where V : T
{
    mappings.Add(typeof(T), typeof(V));
}

And finally, we are going to change our Get method to invoke the constructor of the requested type, after some extra checks:

private static object Get(Type type)
{
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();

    List<object> resolvedParameters = new List<object>();

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

    return constructor.Invoke(resolvedParameters.ToArray());
}

Let’s review this code step by step: The first thing it does is resolving the type, this means checking if we have any mapping available for the specific type, if not, it returns the same type:

private static Type ResolveType(Type type)
{
    if (mappings.Keys.Contains(type))
    {
        return mappings[type];
    }

    return type;
}

After being sure about using the correct type, the next step is retrieving the constructor for the specified type, and the list of its parameters (if any).

...
    var target = ResolveType(type);
    var constructor = target.GetConstructors()[0];
    var parameters = constructor.GetParameters();
...

If the constructor has parameters, then each parameter type it will try to resolve it individually, and if the resolution was successful, it is added to a list of resolved parameters (the order here is very important, as it must match the order of the constructor signature).

    foreach (var item in parameters)
    {
        resolvedParameters.Add(Get(item.ParameterType));
    }

Finally, the constructor is invoked with the parameter list and returns the created object.

    return constructor.Invoke(resolvedParameters.ToArray());

The final syntax for getting a new object from our dependency injector is the following:

Injector.Map<IDataStorage, DataStorage>();
var noteList = Injector.Get<NoteList>();

The result is a very convenient way of generating an object without caring about its dependencies, that may be defined at a way higher level.

Recap

Dependency injection is not an obscure term, it allows us to create uncoupled architectures, and engines like the one we just created allow us to create the required infrastructure at a higer level, so the rest of the classes have only the logic related to its own behavior, with the minimum set of dependencies. It’s also not a very complicated piece of software, although ninject has a way more features and is far more robust that what we have seen here, but this is just step one.

Also, C#’s language features allow us to do some metaprogramming by getting types, parameters of a constructor and invoking it at runtime, which is not bad for a strongly typed language. It would be interesting to see how we could create a version of this injector in a more dynamic, loosely typed environment.

Get the code and play with it!