2010-11-12 56 views
13

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

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

如果我的AuthorizationAttribute依赖于其他组件,以便正确工作,它是什么权利[体系结构]模式,以实现这一目标?

即AuthorizationAttribute取决于IUserRepository ...如何应该这种关系得到解决?

回答

17

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

正确 - 但不要将操作筛选器与可能无法实现它们的属性混淆。用ASP解决这个问题的最简单的方法。即使MVC框架允许您将它们组合起来,.NET 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>(); 

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

+0

谢谢尼克 - 他们都是一个彻底的答案和一个精彩的框架! – Mark 2010-11-15 07:10:20

2

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

如果你使用MVC 3,那么你可以使用MVC Service Location

+2

无论如何,使用CSL如果是服务定位器,那么使用CSL有什么意义?当你知道你的代码将被其他可能更喜欢另一个容器的人重新使用时,通常会使用CSL。不要认为有抽象的理由。 – 2010-11-12 13:41:07

+0

那个人被认为是死亡 - 它总是归结为一种意识形态的观点, – 2010-11-12 13:50:25

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>(); 
     } 
    } 
} 
    ... 
0

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

即使in Asp.Net Mvc3

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

所以 - 接下来最好的事情是属性注入(Mvc3提供了一些开箱即用的支持)。

这是手动完成此操作的how to

我个人使用MvcExtensions。我很好,在different way注册他们。这里是usage

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