2010-07-20 71 views
2

我使用一個注入BLL服務的頁面:一個簡單的服務返回一組對象的使用這樣的功能:ASP.NET:依賴注入和角色

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

但它是非常難看:這是一個服務定位器,它是沒有可擴展的既不測試。

我該如何處理這種情況?也許爲每個角色創建一個子容器?

回答

4

您可以實現它的裝飾複合組合:

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

這是繼單一職責原則,因爲每個實施只做一件事。

+0

一如既往,很好! +1 – Steven 2010-07-20 10:08:36

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

我希望這有助於。