属性中的依赖注入

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


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


江户川乱折腾
浏览 512回答 3
3回答

侃侃尔雅

您应该完全避免将依赖项注入到属性中。本文中对此原因进行了解释:属性中的依赖注入:请勿这样做!。总而言之,本文解释说:构造函数的注入是不可能的,因为Attribute实例的创建不能被拦截。CLR处于控制之中。属性注入的使用很脆弱,因为它会导致时间耦合,应该避免。将依赖项注入属性使得无法验证容器配置的正确性。像MVC和Web API这样的框架缓存了属性,这使得很容易意外地创建引起错误的俘获依赖性。您有两种选择:通过将数据(属性)从其行为(服务)中分离出来,使属性变为被动状态,如参考文章和Mark Seemann的相关文章中所述。如本答案所述,将您的属性转换为不起眼的对象。这意味着您:从属性提取所有逻辑到包含所有依赖项的自定义服务中。在您的容器中注册该服务。让属性的方法(AuthorizeCore根据您的情况)只需要从服务定位器/ DependencyResolver解析服务并调用服务的方法即可。这里要注意的重要一点是,您不能进行构造函数注入,属性注入,并且服务不能以属性私有状态存储(如您已经注意到的)。使用哪个选项:如果您非常希望保持设计整洁,或者您需要使用这种方式应用多个属性,或者要应用的属性是在不依赖于System.Web的程序集中定义的,请使用选项1。 .Mvc。否则,请使用选项2。

隔江千里

我一直在研究option1,如果您为要解析的dbcontext指定了InRequestScope(Ninject),则似乎无法使用它。否则,效果很好。我首先使用服务定位器(反模式)进行了尝试,但解决了服务对象的创建问题。定制授权属性的问题在于,它是在运行时创建的,并不遵循InRequestScope。如果我错了,请纠正我。

LEATH

请再次仔细阅读选项1中提到的文章。在这种情况下,DbContext的生活方式是无关紧要的。属性可以是单例,没有任何问题,因为您无需向属性中注入任何东西。该属性只是数据。但是(一如既往),您必须确保操作筛选器服务的生存期短于或等于其依赖项,因为您将获得专属的依赖项。
打开App,查看更多内容
随时随地看视频慕课网APP