2016-03-31 47 views
0

我有一個由DAL,BLL和API層組成的應用程序,以及使用統一注入的Iam。在業務層,我有一個名爲AuthRepository的類,它從IAuthRepository繼承,下面是這個類的一部分。在三層應用程序中使用Unity

類AuthRepository在BLL:

public class AuthRepository : IAuthRepository, IDisposable 
{ 
    private UserAuthContext _authContext; 
    private UserManager<UserInfo> _userManager; 

    // Issue 1: this constructor should be delete and use injection instead 
    // to solve the problem in class SimpleAuthorizationServerProvider 
    public AuthRepository() 
    { 
     _authContext = new UserAuthContext(); 
     _userManager = new UserManager<UserInfo>(new UserStore<UserInfo>(_authContext)); 
    } 

    public AuthRepository(UserAuthContext authContext) 
    { 
     _authContext = authContext; 
     //this._authContext = new UserAuthContext(); 
     _userManager = new UserManager<UserInfo>(new UserStore<UserInfo>(_authContext)); // TODO: implement usermanager with Unity 
    } 

    public async Task<IdentityResult> RegisterUser(UserEntity createUserModel) 
    { 
     UserInfo user = new UserInfo 
     { 
      FirstName = createUserModel.FirstName, 
      LastName = createUserModel.LastName, 
      UserName = createUserModel.UserName, 
      Email = createUserModel.Email 
     }; 
     var result = await _userManager.CreateAsync(user, createUserModel.Password); 
     return result; 
    } 

在API層I具有另一個類被稱爲SimpleAuthorizationServerProvider,類照顧由Owin以下提供的熊的令牌類

類SimpleAuthorizationServerProvider在API層中:

public class SimpleAuthorizationServerProvider : OAuthAuthorizationServerProvider 
{ 
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context) 
    { 
     // Resource owner password credentials does not provide a client ID. 
     if (context.ClientId == null) 
     { 
      context.Validated(); 
     } 

     return Task.FromResult<object>(null); 
    } 
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

     using (AuthRepository _repo = new AuthRepository()) 
     { 
      IdentityUser user = await _repo.FindUser(context.UserName, context.Password); 

      if (user == null) 
      { 
       context.SetError("invalid_grant", "The user name or password is incorrect."); 
       return; 
      } 
     } 

     var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
     identity.AddClaim(new Claim("sub", context.UserName)); 
     identity.AddClaim(new Claim("role", "user")); 

     context.Validated(identity); 
    } 
} 

問題是AuthRepository中的第一個構造函數應該是remov編輯使應用程序耦合。如果我刪除此構造方法,所以我需要在此聲明

使用發送從方法GrantResourceOwnerCredentials的SimpleAuthorizationServerProvider類類型UserAuthContext的參數(AuthRepository _repo =新AuthRepository())

和這就是我不想做的,API層應該與BLL進行通信而不是DAL。

任何想法如何解決這個問題?

回答

1

我對Unity不熟悉,但通常IoC容器應該注意通過構造函數注入來注入依賴關係。在你的情況下,你應該改變SimpleAuthorizationServerProvider和​​類。

public class SimpleAuthorizationServerProvider 
{ 
    private IAuthRepository _authRepository; 

    public SimpleAuthorizationServerProvider(IAuthRepository authRepository) 
    { 
     _authRepository = authRepository 
    } 

    ... 

    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context) 
    { 
     context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" }); 

     // no need for new repository anymore 
     // class already has repository injected 

     IdentityUser user = await _authRepository.FindUser(context.UserName, context.Password); 

     if (user == null) 
     { 
      context.SetError("invalid_grant", "The user name or password is incorrect."); 
      return; 
     } 

     var identity = new ClaimsIdentity(context.Options.AuthenticationType); 
     identity.AddClaim(new Claim("sub", context.UserName)); 
     identity.AddClaim(new Claim("role", "user")); 

     context.Validated(identity); 
    } 
} 

public class AuthRepository : IAuthRepository, IDisposable 
{ 
    public AuthRepository(UserAuthContext userAuthContext, UserManager<UserInfo> userManager) 
    { 
     _userAuthContext = userAuthContext; 
     _userManager = userManager; 
    } 
    ... 
} 

如果您​​類不需要UserAuthContext(代碼段只使用它來創建一個UserManager<UserInfo>),那麼你可能會從構造函數刪除類和移動是依賴於UserManager<T>類的構造函數:

public class AuthRepository : IAuthRepository, IDisposable 
{ 
    public AuthRepository(UserManager<UserInfo> userManager) 
    { 
     _userManager = userManager; 
    } 
    ... 
} 

public class UserManager<T> 
{ 
    private UserAuthContext _userAuthContext; 

    public UserManager<T>(UserAuthContext userAuthContext) 
    { 
     _userAuthContext = userAuthContext; 
    } 
    ... 
} 

最後,你需要註冊必須使用Unity注入的所有類描述in the documentation

一兩件事:你會如有可能,用接口替換構造函數中的具體類。一般來說,對接口進行編程比對具體類進行編程要好。一個很好的概述,可以發現here

編輯

GrantResourceOnwerCredentials體感強調的是,您不再需要一個新的存儲庫,因爲對象已經進入注入一個。

更新

在你開始補課,你不應該創建一個新的SimpleAuthorizationServerProvider但問abstract factory是對SimpleAuthorizationServerProvider依賴於你做它。

+0

這就是其實我試圖這樣做,但是當我在啓動類註冊SimpleAuthorizationServerProvider,我也會面臨同樣的問題,即構造函數中SimpleAuthorizationServerProvider需要IAuthRepository類型的參數。你是否認爲帶有propreties而不是構造函數的DI可以解決這個問題? –

+0

你應該使用'RegisterType ()'註冊'IAuthRepository'的具體類,如下所示:'yourContainer.RegisterType ();' – venerik

+0

我做了bro,我已經完成了這一步。我的問題是,我必須在GrantResourceOwnerCredentials方法的SimpleAuthorizationServerProvider類中發送UserAuthContext類型的參數 –

1

遵循venerik的指示,所以加一個構造函數IAuthRepository的接口:

public class SimpleAuthorizationServerProvider 
{ 
    private IAuthRepository _authRepository; 

    public SimpleAuthorizationServerProvider(IAuthRepository authRepository) 
    { 
     _authRepository = authRepository 
    } 

    ... 

然後,正如你所說,當你需要傳遞類型的參數「在啓動類註冊SimpleAuthorizationServerProvider」 「IAuthRepository」,這可以通過添加以下操作:

var OAuthServerOptions = new OAuthAuthorizationServerOptions() 
     { 
      AllowInsecureHttp = true, 
      TokenEndpointPath = new PathString("/token"), 
      AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(60), 
      Provider = new SimpleAuthorizationServerProvider((IAuthRepository)GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IAuthRepository))) 
     }; 

在上面的代碼中提供商 i行你需要注入你的具體課程。

p.s.我假設你正在註冊您的統一配置在Owin啓動文件即

public class Startup 
{ 
    public void Configuration(IAppBuilder app) 
    { 
     UnityConfig.RegisterComponents(); 
     ConfigureOAuth(app); 
     ... 
+0

我可以在下週給出一個更詳細的例子,現在太多了,對不起。 – Palvinder

相關問題