1

我正在關注Onion體系結構並使用Identity Framework。在我的核心項目,我有:簡單注射器身份UserManager <AppUser,Int32>註冊錯誤

public interface IUserRepository : IDisposable 
{ 
    // Repository methods....... 
} 

在我Architecture.Repository,我有

public class UserRepository : IUserRepository 
{ 
    // This is Identity UserManager 
    private readonly UserManager<AppUser, int> _userManager; 
    private readonly IAuthenticationManager _authenticationManager; 
    private bool _disposed; 

    public UserRepository(UserManager<User, int> userManager, 
     IAuthenticationManager authenticationManager) 
    { 
      _userManager = userManager; 
      _authenticationManager = authenticationManager; 
    } 
} 

在我的解決依賴的項目,我有:

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(IocConfig), 
    "RegisterDependencies")] 
namespace AdShad.Infrastructure.DependencyResolution 
{ 
    public class IocConfig 
    { 
     public static void RegisterDependencies() 
     { 
      var container = new Container(); 
      container.RegisterWebApiRequest<IUnitOfWork, UnitOfWork>(); 
      container.RegisterWebApiRequest<IUserRepository, UserRepository>(); 

      container.RegisterManyForOpenGeneric(typeof(IRepository<>), 
       typeof(BaseRepository<>).Assembly); 
      container.RegisterWebApiRequest<IEntitiesContext, MyContext>(); 

      container.RegisterWebApiRequest(
       () => HttpContext.Current.GetOwinContext().Authentication); 

      container.Verify(); 

      HttpConfiguration config = new HttpConfiguration 
      { 
       DependencyResolver = 
        new SimpleInjectorWebApiDependencyResolver(container) 
      }; 
     } 
    } 
} 

container.Verify(),我我得到以下錯誤:

An exception of type 'System.InvalidOperationException' occurred in SimpleInjector.dll but was not handled in user code

Additional information: The configuration is invalid. Creating the instance for type IUserRepository failed. The registered delegate for type IUserRepository threw an exception. No registration for type UserManager could be found and an implicit registration could not be made. The constructor of type UserManager contains the parameter of type IUserStore with name 'store' that is not registered. Please ensure IUserStore is registered, or change the constructor of UserManager.

有人可以指導我做錯了什麼,我需要做些什麼來糾正它?

+0

但是你沒有在容器中註冊'UserManager' ......並且異常在說這個,UserManager'構造函數需要'IUserStore'參數,所以SimpleInjector不能創建它。你需要在'UserManager'類的容器或委託中註冊'IUserStore'類 –

+0

但是我沒有任何IUserStore,也沒有那個接口的具體類,我怎麼註冊? –

+0

@UsageKhalid你需要選擇一個'UserStore'實現或者創建你自己的([here](http://www.asp.net/identity/overview/getting-started/adding-aspnet-identity-to-an -empty-or-existing-web-forms-project),[這裏](http://www.asp.net/identity/overview/extensibility/overview-of-custom-storage-providers-for-aspnet-identity)等等) – qujck

回答

5

異常消息說:

The constructor of type UserManager<AppUser, int> contains the parameter of type IUserStore with name 'store' that is not registered. Please ensure IUserStore<AppUser, int> is registered, or change the constructor of UserManager.

例外建議你應該做一個登記IUserStore<AppUser, int>,因爲UserManager<AppUser, int>取決於此。所以,你可以爲實例進行以下注冊:

// UserStore<TUser> is defined in Microsoft.AspNet.Identity.EntityFramework. 
// Do note that UserStore<TUser> implements IUserStore<TUser, string>, so 
// this Entity Framework provider requires a string. If you need int, you 
// might have your own store and need to build your own IUserStore implemenation. 
container.Register<IUserStore<AppUser, string>>(
    () => new UserStore<AppUser>>(), 
    Lifestyle.Scoped); 

然而,根據this article,你不應該自動線框架結構類型,如UserManager<TUser, TKey>,而是用手工註冊的,而不是創建這種類型的自己。例如:

container.Register<UserManager<AppUser, string>>(
    () => new UserManager<AppUser, string>(new UserStore<AppUser>()), 
    Lifestyle.Scoped); 

它甚至會更好,不要直接在覈心應用程序使用的類型從外部庫(如UserManager<TUser, TKey>)。特別是因爲你正在練習洋蔥的建築。該體系結構促進了原理並描述了端口和適配器的概念。端口是由應用程序定義的抽象,允許網關進入某個外部域或庫。適配器是實際連接到此外部域或庫的這種抽象的實現。這正是Dependency Inversion Principle(五個SOLID原則之一)所描述的內容。

因此,而不是讓你UserRepository取決於框架類型,如UserManager<TUser, TKey>,讓它取決於customly定義的抽象,用very narrowly definedsingle responsibility。此抽象的適配器可以使用UserManager<TUser, TKey>

根據UserRepository的不同,您甚至可以將其本身作爲適配器。在這種情況下,讓UserRepository直接取決於UserManager<TUser, TKey>是好的。在這種情況下,將UserManager<TUser, TKey>隱藏在額外的抽象之後會導致額外/不必要的抽象層。

但是,適配器不僅可以直接依賴於UserManager<TUser, TKey>,但它可以簡單地控制UserManager<TUser, TKey>本身的創建和銷燬。換句話說,你可以UserRepository如下所示:

// NOTE: Do not let IUserRepository implement IDisposable. This violates 
// the Dependency Inversion Principle. 
// NOTE2: It's very unlikely that UserRepository itself needs any disposal. 
public class UserRepository : IUserRepository 
{ 
    // This is Identity UserManager 
    private readonly IAuthenticationManager _authenticationManager; 

    public UserRepository(IAuthenticationManager authenticationManager) 
    { 
      _authenticationManager = authenticationManager; 
    } 

    public void Delete(AppUser user) { 
     // Here we create and dispose the UserManager during the execution 
     // of this method. 
     using (manager = new UserManager<AppUser, string>(
      new UserStore<AppUser>())) { 
      manager.DeleteAsync(user).Result; 
     } 
    } 
} 

在簡單噴油器的討論有一個interesting description如何與身份和Visual Studio的默認模板的工作。並且here是一個關於標識的Stackoverflow q/a,您可能也會感興趣。

+0

非常感謝。這有很多幫助。其實我對洋蔥建築和簡單的噴油器來說是全新的。客戶端有一些限制,我必須使用使用數據庫第一方法的Onion體系結構和ASP.NET身份框架。根據我的要求,我無法通過互聯網找到足夠的幫助。但無論如何非常感謝。我會覆蓋所有這些文章並嘗試實施它們。 –

+0

我不知道你在這裏想說什麼:「你不應該自動連線框架類型,如UserManager ,但使用手動註冊,而不是自己創建這種類型」。 你想說我不應該自定義身份用戶管理器? –

+0

@UsmanKhalid:不,自動佈線是容器選擇正確構造函數並自動注入正確依賴關係的過程。手動接線是代碼調用構造函數的地方。這就是我的例子。他們在lambda表達式中調用ctor。 – Steven