具有 IOC 的身份框架:“当前类型是一个接口,无法构造”

Gon*_*ing 3 c# asp.net-mvc entity-framework unity-container asp.net-identity

我必须将所有 IdentityFramework 类和接口移至单独的库,这意味着新的Common.Models.Interfaces接口库只能引用其他接口库(或 .net 库)。这意味着我所有的ApplicationUser参数和变量都变成了IApplicationUser

经过几个小时的更改后,我已经全部构建完毕,但在运行时我收到以下错误:

当前类型 Microsoft.AspNet.Identity.IUserStore`1[Common.Models.Interfaces.Account.IApplicationUser] 是一个接口,无法构造。您是否缺少类型映射?

所以我的问题是:我可能会缺少什么类型映射?

我之前已经使用http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registrationdbcontext中的以下代码解决了问题(特别是使用)InjectionConstructor

container.RegisterType<IApplicationUser, ApplicationUser>();
container.RegisterType<DbContext, ApplicationDbContext>();
container.RegisterType<IdentityDbContext<ApplicationUser>, ApplicationDbContext>();
container.RegisterType<IIdentityMessageService, EmailService>();
container.RegisterType<IApplicationSignInManager, ApplicationSignInManager>();
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)

注意:此处提到的其他错误已删除,因为它具有误导性。看起来我需要额外的映射,但不知道是什么。

应用程序的用户界面和类如下(已修剪),以便您可以发现我出错的地方:

IApplicationUser.cs

public interface IApplicationUser : IUser, IUser<string>
{
     ...
}
Run Code Online (Sandbox Code Playgroud)

应用程序用户.cs

public class ApplicationUser : IdentityUser, IApplicationUser
{
     ...
}
Run Code Online (Sandbox Code Playgroud)

应用程序DbContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
Run Code Online (Sandbox Code Playgroud)

显然,不可能包含所有相关代码来重现此问题,因为它运行了 1000 行,并且不需要重现,因此只有 IOC 专家才应申请。:)

第二次尝试:

在获得有用的链接后,@guillaume31我尝试了以下操作:

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<>), new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)

这可以编译,但我收到一个新错误:

GenericArguments[0], 'Common.Models.Interfaces.Account.IApplicationUser', on 'Microsoft.AspNet.Identity.EntityFramework.UserStore`6[TUser,TRole,TKey,TUserLogin,TUserRole,TUserClaim]' 违反了类型参数的约束'T用户'

第三次尝试

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<ApplicationUser>), new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)

结果出现这个错误:

无法转换类型为“Microsoft.AspNet.Identity.EntityFramework.UserStore 1[Vero.Common.Verofy.Models.Account.ApplicationUser]' to type 'Microsoft.AspNet.Identity.IUserStore1[Vero.Common.Verofy.Models.Interfaces.Account.IApplicationUser]”的对象。

第四次尝试

container.RegisterType(typeof(IUserStore<IApplicationUser>), typeof(UserStore<ApplicationUser>), new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)

这可以编译,但我收到此错误(与之前的测试相同):

无法转换类型为“Microsoft.AspNet.Identity.EntityFramework.UserStore 1[Common.Models.Account.ApplicationUser]' to type 'Microsoft.AspNet.Identity.IUserStore1[Common.Models.Interfaces.Account.IApplicationUser]”的对象。

第五次尝试(使用注册实例):

var applicationDbContext = new ApplicationDbContext();
container.RegisterInstance<DbContext>(applicationDbContext);
var userStore = new UserStore<ApplicationUser>(applicationDbContext);
container.RegisterInstance(typeof(IUserStore<IApplicationUser>), userStore);
Run Code Online (Sandbox Code Playgroud)

新的错误是:

类型 Microsoft.AspNet.Identity.EntityFramework.UserStore 1[[Vero.Common.Verofy.Models.Account.ApplicationUser, Vero.Common.Verofy.Models, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]] cannot be assigned to variables of type Microsoft.AspNet.Identity.IUserStore1[Vero.Common.Verofy.Models.Interfaces.Account.IApplicationUser]。参数名称:实例

第六次尝试(绕过注入):

下面的简单行在运行时也会失败:

IUserStore<IApplicationUser> test = (IUserStore<IApplicationUser>)new UserStore<ApplicationUser>(applicationDbContext);
Run Code Online (Sandbox Code Playgroud)

错误是:

无法转换类型>“Microsoft.AspNet.Identity.EntityFramework.UserStore 1[Common.Models.Account.ApplicationUser]' to type 'Microsoft.AspNet.Identity.IUserStore1[Common.Models.Interfaces.Account.IApplicationUser]”的对象。

概括

IUserStore<IApplicationUser>所有这些问题都表明我和我的类实现之间存在不兼容性UserStore<ApplicationUser>。询问您认为可能有帮助的任何课程的更多详细信息。

更新

基本问题归结为这种依赖性:

  • 我们ApplicationUser班需要揭露public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<ApplicationUser, string> manager)
  • 这会强制UserManager类型为 IApplicationUser 而不是应用程序用户,并导致发生大量级联依赖关系。

sow*_*wen 5

这是我一直在使用的

        container.RegisterType<IUserStore<IdentityUser>, UserStoreRepository>(new PerRequestLifetimeManager());
        container.RegisterType<IRoleStore<IdentityRole, string>, RoleStoreRepository>(new PerRequestLifetimeManager());

        container.RegisterType<ApplicationUserManager>(new PerRequestLifetimeManager());
        container.RegisterType<ApplicationRoleManager>(new PerRequestLifetimeManager());
Run Code Online (Sandbox Code Playgroud)

UserStoreRepository 只是

public class UserStoreRepository : UserStore<IdentityUser>
{
    public UserStoreRepository(AuthContext context)
        : base(context)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

相似地

public class RoleStoreRepository : RoleStore<IdentityRole>
{
    public RoleStoreRepository(AuthContext context)
        : base(context)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

当然你需要注册上下文

public class AuthContext: IdentityDbContext<IdentityUser>
{
    public AuthContext()
        : base("AuthContext")
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

对于其他事情:

public class ApplicationUserManager : UserManager<IdentityUser>

 public class ApplicationRoleManager : RoleManager<IdentityRole>
Run Code Online (Sandbox Code Playgroud)

我认为你的第一次尝试几乎是正确的,我会尝试将你的 UserStore 包装到另一个包装你的 ApplicationUser 的对象中