属性中的依赖注入 [英] Dependency Injection in attributes

查看:126
本文介绍了属性中的依赖注入的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正尝试将依赖项注入到自定义AuthorizeAttribute中,如下所示:

I am trying to inject a dependency into a custom AuthorizeAttribute as follows:

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;
    }
}

这有效,但似乎可以作为一个整体解决,这意味着我遇到了上一个问题中所述的问题

This works but seems to be resolving as a singleton meaning I get the problems described in my pervious question

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

What I'd like to do is use property injection but as my Attribute itself is not resolved by Unity I'm unable to find a way to configure the container to intercept and resolve a property. I have tried the following:

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.

But the property is always null at runtime.

有人做到了吗?如果有,您有例子吗?

Has anyone achieved this and if so do you have an example?

推荐答案

您应该避免完全依赖注入属性.本文中对此原因进行了解释:属性中的依赖项注入:不要这样做!.总而言之,这篇文章解释了这一点:

You should prevent doing dependency injection into attributes completely. The reason for this is explained in this article: Dependency Injection in Attributes: don’t do it!. In summary the article explains that:

  • 无法进行构造函数注入,因为无法拦截Attribute实例的创建;因此,不能进行构造函数注入. CLR处于控制之中.
  • 属性注入的使用非常脆弱,因为它会导致临时耦合,应该避免.
  • 对属性的依赖注入使得无法验证 容器配置的正确性.
  • 诸如MVC和Web API缓存属性的框架,使意外创建强制性依赖会导致错误.
  • Constructor injection is not possible, because creation of an Attribute instance cannot be intercepted; the CLR is in control.
  • The use of property injection is fragile, since it results in Temporal Coupling, which should be prevented.
  • Dependency injection into attributes makes it impossible to verify the correctness of the container's configuration.
  • Frameworks like MVC and Web API cache attributes, making it very easy to accidentally create captive dependencies causing bugs.

您在这里有两个选择:

  1. 按照参考文章马克·塞曼(Mark Seemann)的相关文章.
  2. 按照谦虚对象 stackoverflow.com/a/29318325/264697>此答案.这意味着您:
  1. Make the attributes passive, by splitting the data (the attribute) from its behavior (the service) as explained in the referenced article and this related article from Mark Seemann.
  2. Turn your attributes into humble objects as explained in this answer. This means you:
  1. 将所有逻辑从属性提取到包含所有依赖项的自定义服务中.
  2. 在您的容器中注册该服务.
  3. 让属性的方法(在您的情况下为AuthorizeCore)只不过是从服务定位器/DependencyResolver解析服务并调用服务的方法.这里要注意的重要一点是,您不能进行构造函数注入,属性注入,并且服务不能以属性私有状态存储(如您已经注意到的那样).
  1. extract all logic from the attribute into a custom service that contains all dependencies.
  2. Register that service in your container.
  3. let the attribute's method (AuthorizeCore in your case) do nothing more than resolving the service from the service locator / DependencyResolver and call the service's method. Important to note here is that you cannot do constructor injection, property injection and the service cannot be stored in the attributes private state (as you already noticed).

要使用的选项:

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

这篇关于属性中的依赖注入的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆