我的一个MVC属性依赖于我希望通过构造函数注入的服务。显然,MVC属性也需要无参数构造函数。
public MyAttribute()
{
...
}
public MyAttribute(IMyService)
{
...
}
我在想我可以进行属性注入而不是构造函数注入,但是我的控制器(及其属性)位于一个单独的类库中,没有引用IoC容器。
在没有引用IoC容器的情况下,是否有在属性过滤器中使用服务的方法?
值得我使用Ninject for MVC3
由于
答案 0 :(得分:10)
作为一般解决方案(没有任何对DI框架的特殊集成支持),MVC3会向IDependencyResolver
询问IFilterProvider
。换句话说,诀窍是:
FilterAttributeFilterProvider
集合中删除System.Web.Mvc.FilterProviders
。IDependencyResolver
(如果您还没有这样做)。IFilterProvider
。这看起来像这样:
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框架都支持注入过滤器属性,但没有一个框架有助于解决此问题。因此,更好的解决方案是将属性保持为被动,如here和here所述。
答案 1 :(得分:1)
我几天前试图达到同样的目的。请阅读帖子here内置的绑定过滤器功能。