为了账号安全,请及时绑定邮箱和手机立即绑定

属性中的依赖注入

属性中的依赖注入

C#
江户川乱折腾 2019-11-20 09:43:05
我正在尝试将依赖项注入到自定义中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。有没有人做到这一点,如果有,您有榜样吗?
查看完整描述

3 回答

?
侃侃尔雅

TA贡献1801条经验 获得超16个赞

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

  • 构造函数的注入是不可能的,因为Attribute实例的创建不能被拦截。CLR处于控制之中。

  • 属性注入的使用很脆弱,因为它会导致时间耦合,应该避免。

  • 将依赖项注入属性使得无法验证容器配置的正确性。

  • 像MVC和Web API这样的框架缓存了属性,这使得很容易意外地创建引起错误的俘获依赖性。

您有两种选择:

  1. 通过将数据(属性)从其行为(服务)中分离出来,使属性变为被动状态,如参考文章和Mark Seemann的相关文章中所述。

  2. 如本答案所述,将您的属性转换为不起眼的对象。这意味着您:

    1. 从属性提取所有逻辑到包含所有依赖项的自定义服务中。

    2. 在您的容器中注册该服务。

    3. 让属性的方法(AuthorizeCore根据您的情况)只需要从服务定位器/ DependencyResolver解析服务并调用服务的方法即可。这里要注意的重要一点是,您不能进行构造函数注入,属性注入,并且服务不能以属性私有状态存储(如您已经注意到的)。

使用哪个选项:

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

  • 否则,请使用选项2。


查看完整回答
反对 回复 2019-11-20
?
隔江千里

TA贡献1906条经验 获得超10个赞

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

查看完整回答
反对 回复 2019-11-20
?
LEATH

TA贡献1936条经验 获得超6个赞

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

查看完整回答
反对 回复 2019-11-20
  • 3 回答
  • 0 关注
  • 511 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信