lunes, mayo 24, 2010

MEF Parte 4 - Imports

Usando el mismo ejemplo de la aplicación “Saludador” (Iniciada en el Lanzamiento de VisualStudio 2010 en Tijuana) en el siguiente video muestro otras opciones al momento de importar partes de nuestro objeto usando MEF. En concreto ImportingConstructor y AllowDefault.

Entradas Relacionadas:
Introducción a MEF Parte 1
Introducción a MEF Parte 2
Introducción a MEF Parte 3 - Recomposición

sábado, mayo 22, 2010

Introducción a MEF Parte 3 - Recomposición

Continuando con la aplicación de ejemplo sobre MEF, en esta ocasión muestro el concepto de recomposición de MEF. El cual permite cargar componentes de forma dinámica mientras nuestra aplicación corre.

Algo a notar con este ejemplo fue que lo realice utilizando la librería de MEF que se encuentra en codeplex, usando VisualStudio 2008 con el .Net Framework 3.5. En lugar de utilizar VS2010 con el .Net 4.0 como lo había venido haciendo. Por ahora el código es el mismo para ambas versiones del framework.

Como siempre mi meta es que estos videos (screencasts) no pasen de 5 min, por lo tanto si fui muy rápido, me falto algo o me equivoque, les agradeceré sus comentarios.

También se puede ver el video desde screencast.com

Post Relacionados:
Introducción a MEF Parte 1
Introducción a MEF Parte 2

viernes, mayo 21, 2010

Como usar Unity IoC Container en ASP.NET MVC

Una de las ventajas sobre la plataforma ASP.NET MVC sobre WebForms es que podemos utilizar el principio de inversión de control usando la inyección de dependencias (generalmente a través de los constructores). De tal forma que nuestros controladores reciben parámetros en los constructores. Esto hace que la plataforma MVC no pueda, por si sola (usando el DefaultControllerFactory), construir nuestros controladores usando el constructor que recibe parámetros. Es por ello que vemos ejemplos (como el proyecto plantilla de VisualStudio) donde se sobre carga el constructor con uno que no recibe parámetros y es el propio controlador el encargado de crear sus dependencias. Lo cual va en contra del principio de inversión de control.

Resolver este problema es muy sencillo, basta con crear nuestro propio IControllerFactory que es el contrato que utiliza la plataforma MVC para construir los controladores. En este ejemplo nuestro controller factory hará uso de Unity un Contenedor de dependencias (IoC container) para administrar las dependencias.

La forma mas sencilla de crear un IControllerFactory es heredar del DefaultControllerFactory y redefinir el método GetControllerInstance. Aquí muestro el código:

public class UnityControllerFactory: DefaultControllerFactory
{
readonly IUnityContainer container;

public UnityControllerFactory(IUnityContainer container)
{
this.container = container;
}

protected override IController GetControllerInstance(
RequestContext requestContext, Type controllerType)
{
if (controllerType == null )
return null;

return (IController)container.Resolve(controllerType);
}
}





Como puede verse el UnityControllerFactory recibe un contenedor con las dependencias registradas, el cual utiliza para crear los controladores en el método GetControllerInstance. No hace falta registrar los controladores en el contenedor ya que Unity puede construir instancias de tipos no registrados.



Una vez creado nuestro controller factory es necesario indicarle a MVC (en concreto al ControllerBuilder) que utilice nuestro UnityControllerFactory para crear los controladores; el código queda algo así:




var container = new UnityContainer();
//aqui se registran las dependencias
ControllerBuilder.Current.SetControllerFactory(
new UnityControllerFactory(container));





Esto se debe ejecutar al iniciar la aplicación (el Application_Start() en el Global.asax.cs).



Como puede verse con muy poco código podemos estar usando un IoC container en nuestra aplicación ASP.NET MVC, no es complicado y el UnityControllerFactory puede reutilizarse en otras aplicaciones MVC. Así que, ya lo saben, no hay pretexto para no utilizar un contenedor de dependencias.

jueves, mayo 20, 2010

Singleton por cada HTTP Request usando Unity IoC

Hay ocasiones en las que necesitamos tener un objeto compartido por varios objetos en nuestra aplicacion web, similar al patrón singleton, pero solo para esa petición HTTP. Es decir sin compartirlo en toda la aplicación.

Hace tiempo escribí sobre como compartir un LinqToSql DataContext por cada request en una aplicación web. Ahora utilizando Unity podemos lograr ese comportamiento y dejar que el contenedor de dependencias se encargue de darnos la instancia adecuada.

Para manejar el tiempo de vida de las instancias unity utiliza lo que llama LifetimeManager, entonces lo primero que debemos hacer es crear nuestro LifetimeManager, en este caso lo llamaré HttpRequestLifetimeManager y heredamos de la clase abstracta Microsoft.Practices.Unity.LifetimeManager y debemos de definir 3 metodos GetValue, RemoveValue y SetValue.

public class HttpRequestLifetimeManager: LifetimeManager
{
object key;

public HttpRequestLifetimeManager(): this(null)
{
}

public HttpRequestLifetimeManager(object key)
{
this.key = key;
}

public override object GetValue()
{
if (key == null) return null;
return HttpContext.Current.Items[key];
}

public override void RemoveValue()
{

}

public override void SetValue(object newValue)
{
if (key == null)
key = newValue.GetType();

HttpContext.Current.Items[key] = newValue;
}
}


Lo que hace el HttpRequestLifetimeManager es guardar la instancia de la clase en el Items dictionary con el key que se le especifique en el constructor, si no se ha especificado un key, entonces utilizará el tipo del objeto para identificarlo en el diccionario.


Una vez teniendo nuestro LifetimeManager solo es cuestión de especificarle a unitity, al momento de registrar nuestro tipo, que utilice nuestro HttpRequestLifetimeManager para manejar el tiempo de vida de nuestra instancia.


Por ejemplo supongamos que tenemos declarados algunas clases (posiblemente repositorios) que recibe el constructor un DataContext algo como esto:


public class UserRepository : IUserRepository       
{
readonly MyDataContext db;

public UserRepository(MyDataContext db)
{
this.db = db;
}
...

Si queremos que todos nuestros repositorios compartan el mismo MyDataContext por cada request, entonces configuramos nuestro contenedor (generalmente en el Global.asx.cs) de la siguiente manera:


var container = new UnityContainer();                             

container.RegisterType<IAccountRepository, AccountRepository>();
container.RegisterType<IUserRepository, UserRepository>();

container.RegisterType<MyDataContext>(
new HttpRequestLifetimeManager(), new InjectionConstructor());

Ahí podemos ver como al registrar MyDataContext paso una instancia de la clase HttpRequestLifetimeManager para usar la misma instancia durante todo el request y además le paso un instancia de InjectionConstructor para indicarle que utilice el constructor sin argumentos de nuestra clase MyDataContext.


Una vez hecho esto nuestro contenedor se encargará de entregarnos repositorios que comparten el mismo datacontext por cada request.