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