一尘不染

属性中的依赖注入

c#

我正在尝试将依赖项注入到自定义中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;
    }
}

这是可行的,但似乎可以作为一个单例解决,这意味着我得到了我以前的问题中描述的问题

我想做的是使用属性注入,但是由于我的属性本身无法被Unity解析,因此我无法找到一种方法来配置容器以拦截和解析属性。我尝试了以下方法:

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"));

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

有没有人做到这一点,如果有,您有榜样吗?


阅读 285

收藏
2020-05-19

共1个答案

一尘不染

您应该完全避免将依赖项注入到属性中。本文中对此原因进行了解释:属性中的依赖注入:请勿这样做!。总而言之,本文解释说:

  • 构造函数的注入是不可能的,因为Attribute实例的创建不能被拦截。CLR处于控制之中。
  • 属性注入的使用很脆弱,因为它会导致时间耦合,应该避免。
  • 将依赖项注入属性使得无法验证容器配置的正确性。
  • 像MVC和Web API这样的框架缓存了属性,这使得很容易意外地创建引起错误的俘获依赖性

您有两种选择:

  1. 通过将数据(属性)从其行为(服务)中分离出来,使属性变为被动状态,如参考文章和Mark Seemann的相关文章中所述
  2. 本答案所述,将您的属性转换为不起眼的对象。这意味着您:
    1. 从属性提取所有逻辑到包含所有依赖项的自定义服务中。
    2. 在您的容器中注册该服务。
    3. 让属性的方法(AuthorizeCore根据您的情况)只需要从服务定位器/ DependencyResolver解析服务并调用服务的方法即可。这里要注意的重要一点是,您不能进行构造函数注入,属性注入,并且服务不能以属性私有状态存储(如您已经注意到的)。

使用哪个选项:

  • 如果您非常希望保持设计整洁,或者您需要使用这种方式应用多个属性,或者要应用的属性是在不依赖于System.Web的程序集中定义的,请使用选项1。 .Mvc。
  • 否则,请使用选项2。
2020-05-19