具有MVC属性的IoC / DI

时间:2011-10-11 09:50:01

标签: asp.net-mvc-3 ninject ioc-container

我的一个MVC属性依赖于我希望通过构造函数注入的服务。显然,MVC属性也需要无参数构造函数。

    public MyAttribute()
    {
       ... 
    }

    public MyAttribute(IMyService)
    {
      ...
    }

我在想我可以进行属性注入而不是构造函数注入,但是我的控制器(及其属性)位于一个单独的类库中,没有引用IoC容器。

在没有引用IoC容器的情况下,是否有在属性过滤器中使用服务的方法?

值得我使用Ninject for MVC3

由于

2 个答案:

答案 0 :(得分:10)

作为一般解决方案(没有任何对DI框架的特殊集成支持),MVC3会向IDependencyResolver询问IFilterProvider。换句话说,诀窍是:

  1. FilterAttributeFilterProvider集合中删除System.Web.Mvc.FilterProviders
  2. 为您的特定DI框架注册IDependencyResolver(如果您还没有这样做)。
  3. 在容器中注册可以注入任何请求属性属性的自定义IFilterProvider
  4. 这看起来像这样:

    var container = new [your favorite container];
    
    // 1. Remove the FilterAttributeFilterProvider from the collection.
    var providers = FilterProviders.Providers
        .OfType<FilterAttributeFilterProvider>().ToList();
    
    providers.ForEach(p => FilterProviders.Providers.Remove(p));
    
    // 2. Register a IDependencyResolver
    DependencyResolver.SetResolver(new YourDiResolver(container));
    
    // 3. Register a customer IFilterProvider.
    container.Register<IFilterProvider, YourAttributeFilterProvider>();
    

    YourAttributeFilterProvider将如下所示:

    private class YourAttributeFilterProvider
        : FilterAttributeFilterProvider
    {
        private readonly [your favorite container] container;
    
        public YourAttributeFilterProvider(
            [your favorite container] container)
            : base(false)
        {
            this.container = container;
        }
    
        public override IEnumerable<Filter> GetFilters(
            ControllerContext controllerContext, 
            ActionDescriptor actionDescriptor)
        {
            var filters = base.GetFilters(controllerContext,
                actionDescriptor).ToList();
    
            // Inject properties into attribute here.
            filters.ForEach(f => container.InjectProperties(f.Instance));
    
            return filters;
        }
    }
    

    许多框架,如Ninject和Autofac,都通过其MVC集成包内置了对此的支持。了解如何手动执行此操作仍然很有价值。

    警告:

    关于MVC过滤器属性中的依赖注入的一个重要警告。 MVC caches attributes并在app域的持续时间内重复使用实例。这意味着他们几乎成为单身人士,他们拖着他们的依赖。换句话说:那些依赖关系也将成为单身人士,也被称为captive dependency problem。 因此,请确保您只将单例注入您的属性,因为如果不这样做,您的生产系统将受到并发错误的困扰。

    尽管大多数DI框架都支持注入过滤器属性,但没有一个框架有助于解决此问题。因此,更好的解决方案是将属性保持为被动,如herehere所述。

答案 1 :(得分:1)

我几天前试图达到同样的目的。请阅读帖子here内置的绑定过滤器功能。