【问题标题】:ASP.NET: dependency injection and rolesASP.NET:依赖注入和角色
【发布时间】:2011-03-18 07:43:12
【问题描述】:

我有一个使用注入 BLL 服务的页面:一个简单的服务返回一组对象,其函数如下:

public IMyService { List<Foo> All(); }

普通用户有一个默认实现。 现在,我需要管理角色的用户可以查看更多对象,以及服务的另一个实现。

我可以在哪里配置我的页面以使用第二种实现方式?

我的第一个方案是把依赖放到页面中的IUnityContainer中,用它来解决依赖:

[Dependency]
public IUnityContainer Container { get; set;}

Page_Init(..) 
{ 
    _myService = User.IsInRole(MyRoles.Administrators)
                 ? Container.Resolve<IMyService>("forAdmins")
                 : Container.Resolve<IMyService>();
}

但它非常难看:它是一个 ServiceLocator,既不可扩展也不可测试。

我该如何处理这种情况?也许为每个角色创建一个子容器?

【问题讨论】:

    标签: c# asp.net dependency-injection unity-container roles


    【解决方案1】:

    我同意你的观点,你目前的设计很丑。我个人不喜欢这种方法的地方是您在页面内设置安全配置。当有人忘记这一点时,您将遇到安全错误,您如何测试此页面配置是否正确?

    这里有两个想法: 第一的: 使用能够根据用户角色解析该服务的正确实现的工厂:

    public static class MyServiceFactory
    {
        public static IMyService GetServiceForCurrentUser()
        {
            var highestRoleForUser = GetHighestRoleForUser();
    
            Container.Resolve<IMyService>(highestRoleForUser);
        }
    
        private static string GetHighestRoleForUser()
        {
            var roles = Roles.GetRolesForUser().ToList();
            roles.Sort();
            return roles.Last();
        }
    }
    

    第二: 在该界面上有多种方法,一种用于普通用户,一种用于管理员。该接口的实现可以在受限方法上定义PrincipalPermissionAttribute

    class MyServiceImpl : IMyService
    {
        public List<Foo> All()
        {
           // TODO
        }
    
        [PrincipalPermission(SecurityAction.Demand, Role ="Administrator")]
        public List<Foo> AllAdmin()
        {
           // TODO
        }
    }
    

    我希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      您可以将其实现为 DecoratorComposite 的组合:

      public SelectiveService : IMyService
      {
          private readonly IMyService normalService;
          private readonly IMyService adminService;
      
          public SelectiveService(IMyService normalService, IMyService adminService)
          {
              if (normalService == null)
              {
                  throw new ArgumentNullException("normalService");
              }
              if (adminService == null)
              {
                  throw new ArgumentNullException("adminService");
              }
      
              this.normalService = normalService;
              this.adminService = adminService;
          }
      
          public List<Foo> All()
          {
              if(Thread.CurrentPrincipal.IsInRole(MyRoles.Administrators))
              {
                  return this.adminService.All();
              }
              return this.normalService.All();
          }
      }
      

      这遵循单一职责原则,因为每个实现只做一件事。

      【讨论】:

        猜你喜欢
        • 2010-10-27
        • 2015-10-20
        • 2010-12-05
        • 1970-01-01
        • 1970-01-01
        • 2014-07-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多