问题描述
这是设置。说我有一些需要一个服务实例的动作过滤器:
Here's the setup. Say I have some action filter that needs an instance of a service:
public interface IMyService
{
void DoSomething();
}
public class MyService : IMyService
{
public void DoSomething(){}
}
然后我有一个ActionFilter需要该服务的一个实例:
I then have an ActionFilter that needs an instance of that service:
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注入依赖关系到动作过滤器中在屁股上有一点疼痛。最常见的方法是使用自定义操作调用器,如下所示:
Incidentally, here's another nice approach for doing this in MVC3 using the new IFilterProvider interface: http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in-asp-net-mvc-3
推荐答案
修改:稍微阅读后,似乎接受的方式是通过注入资源:
Edit: After a little reading up, it appears that the accepted way to do this is via property injection:
public class MyActionFilter : ActionFilterAttribute
{
[Injected]
public IMyService MyService {get;set;}
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
MyService.DoSomething();
base.OnActionExecuting(filterContext);
}
}
关于为什么不使用服务定位器问题:它大多只是降低依赖注入的灵活性。例如,如果您正在注入日志记录服务,并且想要自动将日志记录服务的注册类别注册到该日志服务中,该怎么办?如果使用构造函数注入,那将会很好。如果您使用的是依赖解决方案/服务定位器,那么您将失去运气。
Regarding the why not use a Service Locator question: It mostly just reduces the flexibility of your dependency injection. For example, what if you were injecting a logging service, and you wanted to automatically give the logging service the name of the class it's being injected into? If you use constructor injection, that would work great. If you're using a Dependency Resolver/Service Locator, you'd be out of luck.
由于这被接受为答案,我想记录下来说我喜欢,因为它将Action Filter的职责与属性分离开来。此外,Ninject的MVC3扩展具有通过绑定配置动作过滤器的一些非常强大的方法。有关详细信息,请参阅以下参考资料:
Since this got accepted as the answer, I'd like to go on the record to say that I prefer Mark Seeman's approach because it separates the Action Filter responsibility away from the Attribute. Furthermore, Ninject's MVC3 extension has some very powerful ways to configure action filters via bindings. See the following references for more details:
- https://github.com/ninject/ninject.web.mvc/wiki/Dependency-injection-for-filters
- https://github.com/ninject/ninject.web.mvc/wiki/Conditional-bindings-for-filters
- https://github.com/ninject/ninject.web.mvc/wiki/Filter-configurations
由于@usr在下面的评论中指出, ActionFilterAttribute
在类加载时被实例化,并且它们持续整个应用程序的整个生命周期。如果 IMyService
接口不应该是一个Singleton,那么它最终会成为一个。如果它的实现不是线程安全的,你可能会遇到很多痛苦。
As @usr pointed out in the comments below, ActionFilterAttribute
s are instantiated when the class is loaded, and they last the entire lifetime of the application. If the IMyService
interface is not supposed to be a Singleton, then it ends up being a Captive Dependency. If its implementation isn't thread-safe, you could be in for a lot of pain.
每当你有一个比你的班级的预期寿命更短的生命周期的依赖,注入工厂以按需生产依赖性是明智的,而不是直接注入。
Whenever you have a dependency with a shorter lifespan than your class's expected lifespan, it's wise to inject a factory to produce that dependency on-demand, rather than injecting it directly.
这篇关于注入依赖于ASP.NET MVC 3动作过滤器。这种方法有什么问题?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!