简单的注入器标识UserManager <AppUser,Int32>注册错误

Usm*_*lid 3 c# asp.net dependency-injection simple-injector asp.net-identity

我正在关注Onion Architecture并使用Identity Framework.在我的核心项目中,我有:

public interface IUserRepository : IDisposable
{
     // Repository methods.......
}
Run Code Online (Sandbox Code Playgroud)

在我的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;
     }
}
Run Code Online (Sandbox Code Playgroud)

在我的依赖解析项目中,我有:

[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)
            };
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

container.Verify(),我收到以下错误:

SimpleInjector.dll中出现"System.InvalidOperationException"类型的异常,但未在用户代码中处理

附加信息:配置无效.为IUserRepository类型创建实例失败.类型IUserRepository的已注册委托引发了异常.无法找到UserManager类型的注册,也无法进行隐式注册.UserManager类型的构造函数包含IUserStore类型的参数,其名称为"store",未注册.请确保已注册IUserStore,或更改UserManager的构造函数.

有人可以指导我做错了什么以及我需要做些什么来纠正它?

Ste*_*ven 8

异常消息说:

UserManager <AppUser,int>类型的构造函数包含IUserStore类型的参数,其名称为"store",未注册.请确保已注册IUserStore <AppUser,int>,或更改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);
Run Code Online (Sandbox Code Playgroud)

但是,根据这篇文章,你不应该自动连接框架类型UserManager<TUser, TKey>,但是使用手动注册而不是自己创建这样的类型.例如:

container.Register<UserManager<AppUser, string>>(
    () => new UserManager<AppUser, string>(new UserStore<AppUser>()),
    Lifestyle.Scoped);
Run Code Online (Sandbox Code Playgroud)

最好不要UserManager<TUser, TKey>直接在核心应用程序中使用外部库(例如)中的类型.特别是因为你正在练习洋葱建筑.此体系结构促进了SOLID原则,并描述了端口和适配器的概念.端口是由应用程序定义的抽象,允许网关进入某个外部域或库.适配器是这种抽象的实现,实际上连接到此外部域或库.这正是依赖性倒置原则(五个SOLID原则之一)所描述的内容.

因此,不要让UserRepository依赖于框架类型,例如UserManager<TUser, TKey>,让它依赖于定制的抽象,具有非常狭窄的定义单一的责任.这种抽象的适配器可以依次使用UserManager<TUser, TKey>.

根据具体UserRepository情况,您甚至可以将其视为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;
         }
     }
}
Run Code Online (Sandbox Code Playgroud)

在Simple Injector讨论中,有一个关于如何使用Identity和Visual Studio的默认模板的有趣描述.而这里是关于身份出现StackOverflow Q/A,你可能会发现有趣的为好.