注入依赖到ASP.NET MVC 3行动的过滤器。有什么不对这种做法? [英] Injecting dependencies into ASP.NET MVC 3 action filters. What's wrong with this approach?

查看:143
本文介绍了注入依赖到ASP.NET MVC 3行动的过滤器。有什么不对这种做法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面的设置。说我有一些行动的过滤器,需要服务的一个实例:

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注入依赖付诸行动的过滤器是有点在屁股痛。最常见的方法是使用自定义操作调用如可以在这里看到:<一href=\"http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/\">http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/这种解决方法背后的主要动机是因为这下面的方法被认为是与容器草率和紧耦合:

In MVC 1/2 injecting dependencies into action filters was a bit of a pain in the ass. The most common approach was to use a custom action invoker as can be seen here: http://www.jeremyskinner.co.uk/2008/11/08/dependency-injection-with-aspnet-mvc-action-filters/ The main motivation behind this workaround was because this following approach was considered sloppy and tight coupling with the container:

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。

Here we're using constructor injection and overloading the constructor to use the container and inject the service. I do agree that does tightly couple the container with the ActionFilter.

我的思想的问题是:现在,在ASP.NET MVC 3,我们在那里有正在使用的容器的抽象(通过DependencyResolver)是所有这些篮球还是必要的?请允许我演示:

My question though is this: Now in ASP.NET MVC 3, where we have an abstraction of the container being used (through the DependencyResolver) are all these hoops still necessary? Allow me to demonstrate:

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在测试时的构造和注入模拟服务的方式。你不是被绑在DI容器的任何实现,因为你正在使用的DependencyResolver,所以是否有任何缺点这种做法?

Now I know that some purists might scoff at this, but seriously, what would be the downside? It's still testable as you can use the constructor that takes an IMyService at test time and inject a mock service that way. You're not tied down to any implementation of DI container since you're using the DependencyResolver, so are there any downsides to this approach?

顺便说一下,以下是使用新IFilterProvider接口MVC3这样做的另一个不错的方法:<一href=\"http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in-asp-net-mvc-3\">http://www.thecodinghumanist.com/blog/archives/2011/1/27/structuremap-action-filters-and-dependency-injection-in-asp-net-mvc-3

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

推荐答案

<击>我还不能肯定,但我相信你可以只使用一个空的构造(为的属性的一部分)和然后有实际注入的价值构造(为的过滤器的一部分)。*

I'm not positive, but I believe you can just use an empty constructor (for the attribute part) and then have a constructor that actually injects the value (for the filter part).*

修改:经过一点点读了起来,看来该接受的方式做,这是通过属性注:

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.

由于这个被录取的答案,我想去哪就记录说,我preFER <一个href=\"http://stackoverflow.com/questions/7192543/injecting-depdencies-into-asp-net-mvc-3-action-filters-whats-wrong-with-this-ap/7194467#7194467\">Mark西曼的做法的,因为它分隔措施筛选责任从属性了。此外,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 加载类的当s被实例化,他们最后应用的整个生命周期。如果 IMyService 接口不应该是一个单身,那么它最终是一个的圈养依赖。如果它的实现不是线程安全的,你可以为一个很大的痛苦在

As @usr pointed out in the comments below, ActionFilterAttributes 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行动的过滤器。有什么不对这种做法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆