Asp.net mvc 如何解决MVC过滤器属性中的依赖项注入问题

Asp.net mvc 如何解决MVC过滤器属性中的依赖项注入问题,asp.net-mvc,dependency-injection,filter,autofac,Asp.net Mvc,Dependency Injection,Filter,Autofac,我有一个从AuthorizationAttribute派生的自定义属性类,它对控制器操作执行自定义安全性。OnAuthorizationCore方法依赖于各种其他组件(例如DAL)来审核用户是否可以调用操作 我正在使用Autofac进行依赖项注入。ExtensionActionInvoker声称能够对操作过滤器执行属性注入。在运行时设置属性的属性(这似乎不是一个好主意)将在简单的单元测试中起作用,但在繁忙的多线程web服务器中,它肯定会出错,因此这种想法似乎是一种反模式。因此,这个问题: 如果我

我有一个从AuthorizationAttribute派生的自定义属性类,它对控制器操作执行自定义安全性。OnAuthorizationCore方法依赖于各种其他组件(例如DAL)来审核用户是否可以调用操作

我正在使用Autofac进行依赖项注入。ExtensionActionInvoker声称能够对操作过滤器执行属性注入。在运行时设置属性的属性(这似乎不是一个好主意)将在简单的单元测试中起作用,但在繁忙的多线程web服务器中,它肯定会出错,因此这种想法似乎是一种反模式。因此,这个问题:

如果我的AuthorizationAttribute依赖于其他组件才能正常工作,那么什么是正确的[architecture]模式才能实现这一点


i、 e.AuthorizationAttribute取决于IUserRepository。。。这种关系应该如何解决?

在MVC2之前,没有直接的解决方法。这里详细介绍了一种有趣的技术:。我建议使用来抽象这一点,并找到您的DI容器


如果您使用的是MVC 3,那么您可以使用

我认为实现这一点最简单的方法是咬紧牙关,接受对autofac本身的依赖。虽然对国际奥委会的依赖本身就是一种反模式,但它在某种程度上更容易缓和。可以按如下方式实现属性:

public class UserAuthorizeAttribute : AuthorizeAttribute
{            
    public IUserRepository CurrentUserService
    {
        get
        {
            var cpa = (IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
            var cp = cpa.ContainerProvider;
            return cp.RequestLifetime.Resolve<IUserRepository>();
        }
    }
}
     ...
public类UserAuthorizeAttribute:AuthorizeAttribute
{            
公共IUserRepository CurrentUserService
{
得到
{
var cpa=(IContainerProviderAccessor)HttpContext.Current.ApplicationInstance;
var cp=cpa.ContainerProvider;
返回cp.RequestLifetime.Resolve();
}
}
}
...

构造函数注入似乎不可能改变过滤器注册的方式

甚至:

依赖项注入在过去很困难的一个地方是过滤器属性本身。由于.NET framework运行时实际上负责创建这些属性实例,因此我们不能使用传统的依赖项注入策略

所以,下一个最好的方法是属性注入(Mvc3提供了一些开箱即用的支持)

这里有一个手动操作的方法

我个人使用MvcExtensions。我很乐意把他们登记在网上。给你

另一件您可能需要调查的事情是项目。与更通用的MvcExtensions项目相比,MvcTurbine主要用于提供依赖注入支持

ExtensionActionInvoker声称能够对操作过滤器执行属性注入

正确-但不要将操作过滤器与可能无法实现它们的属性混淆。在ASP.NET MVC中实现这一点的最干净的方法是划分责任,即使MVC框架允许您将它们组合起来

例如,使用一对类-仅保存数据的属性类:

// Just a regular old attribute with data values
class SomeAttribute : Attribute { ... }
以及已注入依赖项的筛选器:

// Gets dependencies injected
class SomeFilter : IActionFilter { ... }
SomeFilter
只是使用典型的方法,通过
GetCustomAttributes()
从控制器或操作方法获取
SomeAttribute
属性,以完成所需的任何工作

然后可以使用
ExtensibleActionInvoker
连接过滤器:

builder.RegisterControllers(...).InjectActionInvoker();
builder.RegisterType<ExtensibleActionInvoker>().As<IActionInvoker>();
builder.RegisterType<SomeFilter>().As<IActionFilter>();
builder.RegisterController(…).InjectActionInvoker();
builder.RegisterType().As();
builder.RegisterType().As();

它可能比使用“属性作为过滤器”方法编写的代码要多一点,但从长远来看,代码的质量会更好(例如,通过避免属性的限制和服务定位器解决方案的笨拙)。

如果CSL是服务定位器,那么使用CSL有什么意义?当您知道您的代码将被其他可能更喜欢另一个容器的人重用时,通常使用CSL。不要认为还有其他理由可以把它抽象化。这个理由已经争论到了极点——它总是归结为一种意识形态观点,谢谢你,尼克——因为它有一个彻底的答案和一个出色的框架!