Dependency Injection: ASP.NET MVC 3 + Ninject

Vamos con el tercer y último artículo sobre Dependency Injection.

Ésta vez vamos a usar como ejemplo ASP.NET MVC 3. Ésta vez vamos a usar otra librería, en este caso vamos a probar con Ninject.

Ninject es una de las muchas alternativas que hay para implementar Dependency Injection y para mi gusto es de las mejores para ASP.NET MVC.

Vamos a empezar creando la aplicación, la llamaremos MVCWithDI, crearemos una Aplicacion de internet pues ya nos ofrece un Layout básico.

Implementaremos la misma idea que en el artículo anterior:

Creamos una clase llamada Persona:

namespace MVCWithDI.Models
{
    public class Persona
    {
        public string Nombre { get; set; }
        public int Edad { get; set; }
    }
}

Y ahora creamos las interfaces de los servicios que vamos a usar:

namespace MVCWithDI.Abstract
{
    public interface IFechaAEdad
    {
        int Conversion(string fecha);
    }
}
namespace MVCWithDI.Abstract
{
    public interface ICapitalizador
    {
        string Capitalizar(string nombre);
    }
}

Ahora implementamos estos servicios:

using System;
using MVCWithDI.Abstract;

namespace MVCWithDI.Concrete
{
    public class FechaAEdad : IFechaAEdad
    {
        public int Conversion(string fecha)
        {
            int edad;
            var partesfecha = fecha.Split('/');

            // Añadimos el año
            edad = DateTime.Now.Year - Int32.Parse(partesfecha[2]);

            // Comprobamos si hemos cumplido ya este año o no
            if (Int32.Parse(partesfecha[1]) < DateTime.Now.Month) // todavia no hemos cumplido
                edad -= 1; // le restamos un año pues
            if (Int32.Parse(partesfecha[1]) == DateTime.Now.Month)
                if (Int32.Parse(partesfecha[0]) > DateTime.Now.Day) // no ha llegado el dia
                    edad -= 1;

            return edad;
        }
    }
}
using MVCWithDI.Abstract;

namespace MVCWithDI.Concrete
{
    public class Capitalizador : ICapitalizador
    {
        public string Capitalizar(string nombre)
        {
            string nombreCapitalizado = string.Empty;

            var trozoNombre = nombre.Split();

            foreach (var trozo in trozoNombre)
            {
                nombreCapitalizado += char.ToUpper(trozo[0]) + trozo.Substring(1) + " ";
            }

            return nombreCapitalizado.TrimEnd();
        }
    }
}

Ya tenemos los servicios implementados.

Vamos a crear un constructor en el controlador Home y agregar unas referencias:

private readonly IFechaAEdad _fechaAEdad;
private readonly ICapitalizador _capitalizador;

public HomeController(IFechaAEdad fechaAEdad, ICapitalizador capitalizador)
{
	_fechaAEdad = fechaAEdad;
	_capitalizador = capitalizador;
}

Simplemente el constructor recibe un par de referencias de los servicios que usará, al igual que se hizo con el ViewModel en WPF

Ahora vamos a actualizar el método Index:

public ActionResult Index()
{
return View();
}

Simplemente muestra la vista. Vamos a editar ahora la vista (viene creada con el proyecto):

@{
    ViewBag.Title = "ASP.NET MVC 3 con Ninject";
}

@using (Html.BeginForm())
{
    @Html.Label("Nombre y Apellido")
    @Html.TextBox("nombre")
    @Html.Label("Fecha de nacimiento (dd/mm/yyyy)")
    @Html.TextBox("fecha")
    <input type="submit" value="Dale" />
}

Un simple formulario para recoger los datos. Este formulario hará POST en la misma acción Index así que vamos a crear una acción Index solo para peticiones POST que maneje los datos del formulario:

[HttpPost]
public ActionResult Index(string nombre, string fecha)
{
	var persona = new Persona
						{
							Nombre = _capitalizador.Capitalizar(nombre),
							Edad = _fechaAEdad.Conversion(fecha)
						};
	return RedirectToAction("MostrarPersona", persona);
}

Algo simple, del formulario recibe esos dos parametros, los pasamos a sus respectivos servicios y creamos un objeto Persona con esa información.

Ésta acción nos redirige a otra acción, en este caso una llamada MostrarPersona, al cual le pasamos el objeto creado:

public ActionResult MostrarPersona(Persona persona)
{
	return View(persona);
}

Ésta acción simplemente nos muestra una vista a la cual le pasamos el objeto persona.

Bien, vamos a crear esta vista, las opciones quedarán así:

Al poner lo de Details ya nos creará una vista en la cual nos mostrará los datos de la persona, justo lo que necesitamos.

Ya tenemos la aplicación implementada. Ahora necesitamos implementar el Dependency Injection para que funcione.

ASP.NET MVC 3 soporta Dependency Injection sin tener que hacer malabares ni nada extra, ya que antiguamente necesitabamos implementar muchas cosas por nuestra cuenta.

Ahora, simplemente tendremos que implementar IDependencyResolver y pasar esa implementación al framework, veremos como:

Para empezar, necesitamos Ninject bien lo bajas de su web o más comodamente usamos NuGet

PM> install-package Ninject

Ya que tenemos Ninject, vamos a implementar IDependencyResolver:

using System;
using System.Collections.Generic;
using System.Web.Mvc;
using Ninject;

namespace MVCWithDI.Infrastructure
{
    public class NinjectDependencyResolver : IDependencyResolver
    {
        private readonly IKernel _kernel;

        public NinjectDependencyResolver(IKernel kernel)
        {
            _kernel = kernel;
        }

        public object GetService(Type serviceType)
        {
            return _kernel.TryGet(serviceType);
        }

        public IEnumerable<object> GetServices(Type serviceType)
        {
            return _kernel.GetAll(serviceType);
        }
    }
}

IDependencyResolver tiene dos métodos. Con GetService devolvemos el servicio que necesitamos y con GetServices recogemos una colección de dicho servicio.

Nuestra implementación recibe una instancia de IKernel. En Ninject el IKernel es nuestro contenedor, en el cual iremos enlanzado nuestros servicios.

Vale, entonces necesitamos crear dicho contenedor y enlazar nuestros servicios, así que vamos a ello:

using System.Web.Mvc;
using MVCWithDI.Abstract;
using MVCWithDI.Concrete;
using Ninject;

namespace MVCWithDI.Infrastructure
{
    public class NinjectKernelSetup
    {
        public static void Setup()
        {
            var kernel = new StandardKernel();

            kernel.Bind<ICapitalizador>().To<Capitalizador>();
            kernel.Bind<IFechaAEdad>().To<FechaAEdad>();

            DependencyResolver.SetResolver(new NinjectDependencyResolver(kernel));
        }
    }
}

No es nada complicado, ni explicación requiere. A excepción de la última linea. Ahí es donde le decimos al framework que nuestro sistema de Dependency Injection va a ser manejado por Ninject (pasandole la clase que creamos implementando IDependencyResolver).

Por último, necesitamos unir este código con nuestra aplicación, para ello nos vamos al fichero Global.asax.cs y en el método Application_Start insertamos una nueva linea:

protected void Application_Start()
{
	AreaRegistration.RegisterAllAreas();

	RegisterGlobalFilters(GlobalFilters.Filters);
	RegisterRoutes(RouteTable.Routes);

	NinjectKernelSetup.Setup();
}

Ahora ejecutamos la aplicación, insertamos nuestros datos y el resultado será similar a este:

¿Fácil verdad? :)

Tags: , ,

2 comentarios

  1. Fenomenal todos tus post sobre patrones, muy claros y concisos.

    Gracias!
    Juanjo

  2. Excelente post, muy fácil de entender. ¡Mil gracias!

Dejar un comentario