C# ASP.NET:依赖项注入和角色
我有一个使用注入式BLL服务的页面:一个返回一组对象的简单服务,其功能如下:C# ASP.NET:依赖项注入和角色,c#,asp.net,dependency-injection,unity-container,roles,C#,Asp.net,Dependency Injection,Unity Container,Roles,我有一个使用注入式BLL服务的页面:一个返回一组对象的简单服务,其功能如下: public IMyService { List<Foo> All(); } public IMyService{List All();} 对于普通用户,有一个默认实现。 现在,我需要具有管理角色的用户能够通过该服务的另一个实现查看更多对象 在哪里可以配置页面以使用第二个实现 我的第一个解决方案是将依赖关系放到页面中的IUnityContainer,并使用它来解决依赖关系: [Dependency] p
public IMyService { List<Foo> All(); }
public IMyService{List All();}
对于普通用户,有一个默认实现。
现在,我需要具有管理角色的用户能够通过该服务的另一个实现查看更多对象
在哪里可以配置页面以使用第二个实现
我的第一个解决方案是将依赖关系放到页面中的IUnityContainer,并使用它来解决依赖关系:
[Dependency]
public IUnityContainer Container { get; set;}
Page_Init(..)
{
_myService = User.IsInRole(MyRoles.Administrators)
? Container.Resolve<IMyService>("forAdmins")
: Container.Resolve<IMyService>();
}
[依赖关系]
公共IUnityContainer容器{get;set;}
页_Init(…)
{
_myService=User.IsInRole(MyRoles.Administrators)
?容器解析(“foradmin”)
:Container.Resolve();
}
但它非常丑陋:它是一个ServiceLocator,既不可伸缩也不可测试
我如何处理这种情况?也许为每个角色创建一个子容器?我同意你的观点,你当前的设计很难看。我个人不喜欢这种方法的地方在于,您正在页面内设置安全配置。当有人忘记这一点时,您将有一个安全漏洞,您如何测试此页面配置是否正确 这里有两个想法: 第一: 使用能够根据用户角色解决该服务的正确实现的工厂:
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();
}
}
我希望这会有所帮助。您可以将它作为装饰器和复合的组合来实现:
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();
}
}
公共服务:IMyService
{
私有只读IMyService normalService;
私有只读IMyService adminService;
公共服务(IMyService normalService、IMyService adminService)
{
if(normalService==null)
{
抛出新的ArgumentNullException(“normalService”);
}
if(adminService==null)
{
抛出新的ArgumentNullException(“adminService”);
}
this.normalService=normalService;
this.adminService=adminService;
}
公共列表全部()
{
if(Thread.CurrentPrincipal.IsInRole(MyRoles.Administrators))
{
返回此.adminService.All();
}
返回此.normalService.All();
}
}
这遵循单一责任原则,因为每个实施只做一件事
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();
}
}