这是设置。假设我有一些需要服务实例的动作过滤器:
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething(){}
}
然后,我有一个需要该服务实例的ActionFilter:
public class MyActionFilter : ActionFilterAttribute
{
private IMyService _myService; // <--- How do we get this injected
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
_myService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
在MVC 1/2中,将依赖项注入到动作过滤器中有点麻烦。最常见的方法是使用自定义操作调用因为在这里可以看到:http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/的此替代方法的主要动机是因为以下方法被认为与容器不牢固且紧密耦合:
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);
}
}
在这里,我们使用构造函数注入,并重载构造函数以使用容器并注入服务。我同意将容器与ActionFilter紧密耦合。
我的问题是这样的:现在在ASP.NET MVC 3中,我们对正在使用的容器(通过DependencyResolver)进行了抽象,是否还需要所有这些箍?请允许我演示:
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);
}
}
现在我知道有些纯粹主义者可能会对此表示嘲笑,但是认真的说,不利之处是什么?它仍然是可测试的,因为您可以使用在测试时接受IMyService并以这种方式注入模拟服务的构造函数。由于您使用的是DependencyResolver,因此您不会受限于任何DI容器的实现,所以这种方法有不利之处吗?
顺便说一句,这是使用新的IFilterProvider接口在MVC3中执行此操作的另一种好方法:http : //www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in -asp-net-mvc-3