属性注入

我正在试图注入一个自定义的AuthorizeAttribute的依赖如下:

public class UserCanAccessArea : AuthorizeAttribute { readonly IPermissionService permissionService; public UserCanAccessArea() : this(DependencyResolver.Current.GetService<IPermissionService>()) { } public UserCanAccessArea(IPermissionService permissionService) { this.permissionService = permissionService; } protected override bool AuthorizeCore(HttpContextBase httpContext) { string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; bool isAuthorized = false; if (base.AuthorizeCore(httpContext)) isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); return isAuthorized; } } 

这工作,但似乎是解决作为一个单身的含义,我得到的问题在我的前面描述的问题

我想要做的是使用属性注入,但作为我的属性本身不解决的统一我找不到一种方法来configuration容器来拦截和解决属性。 我已经尝试了以下内容:

 public class UserCanAccessArea : AuthorizeAttribute { public IPermissionService permissionService { get; set; } protected override bool AuthorizeCore(HttpContextBase httpContext) { string AreaID = httpContext.Request.RequestContext.RouteData.Values["AreaID"] as string; bool isAuthorized = false; if (base.AuthorizeCore(httpContext)) isAuthorized = permissionService.UserCanAccessArea(AreaID, httpContext.User); return isAuthorized; } } 

容器:

 container.RegisterType<UserCanAccessArea>(new InjectionProperty("permissionService")); 

但是该属性在运行时始终为空。

有没有人做到这一点,如果是的话,你有一个例子吗?

你应该防止完全dependency injection属性。 原因在这篇文章中解释: dependency injection的属性:不要这样做! 。 总之,文章解释说:

  • 构造函数注入是不可能的,因为一个Attribute实例的创build不能被拦截; CLR在控制之中。
  • 财产注入的使用是脆弱的,因为它导致了时间耦合 ,应该防止。
  • dependency injection属性使得无法validation容器configuration的正确性。
  • 像MVC和Web API高速caching属性的框架,使意外地创build俘虏依赖导致错误非常容易。

你有两个select:

  1. 通过从参考文章和Mark Seemann的相关文章中解释数据(属性)的行为(服务),使属性成为被动的。
  2. 按照这个答案的说明将你的属性变成简单的对象 。 这意味着你:
    1. 将属性中的所有逻辑抽取到包含所有依赖关系的自定义服务中。
    2. 在您的容器中注册该服务。
    3. 让属性的方法(你的情况下的AuthorizeCore )除了parsing来自服务定位器/ DependencyResolver的服务外,并且调用服务的方法。 这里需要注意的是,你不能做构造函数注入,属性注入和服务不能存储在属性私人状态(你已经注意到)。

使用哪个选项:

  • 如果您非常希望保持devise清洁,或者您拥有多个您需要应用此属性的属性,或者您想要应用属性在不依赖于System.Web的程序集中定义,请使用选项1 .Mvc。
  • 否则使用选项2。