Aquí está la configuración. Digamos que tengo algún filtro de acción que necesita una instancia de un servicio:
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething(){}
}
Luego tengo un ActionFilter que necesita una instancia de ese servicio:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService; // <--- How do we get this injected
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
En MVC 1/2, inyectar dependencias en filtros de acción fue un poco molesto. El método más común era utilizar un invocador acción personalizada como se puede ver aquí: http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/ la La principal motivación detrás de esta solución fue porque este enfoque siguiente se consideró descuidado y un acoplamiento estrecho con el contenedor:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService;
public MyActionFilter()
:this(MyStaticKernel.Get<IMyService>()) //using Ninject, but would apply to any container
{
}
public MyActionFilter(IMyService myService)
{
_myService = myService;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
Aquí estamos usando la inyección del constructor y sobrecargando el constructor para usar el contenedor e inyectar el servicio. Estoy de acuerdo en que acopla estrechamente el contenedor con ActionFilter.
Sin embargo, mi pregunta es la siguiente: ahora en ASP.NET MVC 3, donde tenemos una abstracción del contenedor que se está utilizando (a través del DependencyResolver), ¿siguen siendo necesarios todos estos aros? Permítame demostrar:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService;
public MyActionFilter()
:this(DependencyResolver.Current.GetService(typeof(IMyService)) as IMyService)
{
}
public MyActionFilter(IMyService myService)
{
_myService = myService;
}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
Ahora sé que algunos puristas podrían burlarse de esto, pero en serio, ¿cuál sería la desventaja? Todavía es comprobable, ya que puede usar el constructor que toma un IMyService en el momento de la prueba e inyectar un servicio simulado de esa manera. No está atado a ninguna implementación de contenedor DI ya que está utilizando DependencyResolver, entonces, ¿hay alguna desventaja en este enfoque?
Por cierto, aquí hay otro buen enfoque para hacer esto en MVC3 usando la nueva interfaz IFilterProvider: http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in -asp-net-mvc-3