如何解决MVC Filter属性中的依赖注入问题

时间:2010-11-12 09:32:26

标签: asp.net-mvc dependency-injection filter autofac

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

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

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

即。 AuthorizationAttribute依赖于IUserRepository ...... 应该如何解决这种关系?

4 个答案:

答案 0 :(得分:17)

  

ExtensibleActionInvoker声称能够在动作过滤器上执行属性注入。

正确 - 但不要将动作过滤器与可能无法实现它们的属性混淆。在ASP.NET MVC中处理此问题的最简单方法是分割职责,即使MVC框架允许您将它们组合在一起。

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

// Just a regular old attribute with data values
class SomeAttribute : Attribute { ... }

并且注入了依赖项的过滤器:

// Gets dependencies injected
class SomeFilter : IActionFilter { ... }

SomeFilter只使用通过SomeAttribute从控制器或操作方法获取GetCustomAttributes()属性的典型方法来执行所需的任何工作。

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

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

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

答案 1 :(得分:2)

在MVC2之前没有直接的方法来做到这一点。这里有一个有趣的技术:http://www.mattlong.com.au/?p=154。我建议使用Common Service Locator对此进行抽象并找到您的DI容器。

如果您使用的是MVC 3,则可以使用MVC Service Location

答案 2 :(得分:2)

我认为实现这一目标的最简单方法是咬紧牙关并接受对autofac本身的依赖。虽然对IoC的依赖本身就是一种反模式,但它更适合。您可以按如下方式实现属性:

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

答案 3 :(得分:0)

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

in Asp.Net Mvc3

  

过去依赖注入困难的地方是过滤器属性本身。因为.NET框架运行时实际上负责创建这些属性实例,所以我们不能使用传统的依赖注入策略。

所以 - 下一个最好的东西是属性注入(Mvc3为开箱即用提供了一些支持)。

这是手动执行此操作的how to

我个人使用MvcExtensions。我可以在different way注册它们。这是usage

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