IOC 的身份框架:"The current type is an interface and cannot be constructed"



我不得不将所有 IdentityFramework 类和接口移动到单独的库中,这意味着新的 Common.Models.Interfaces 接口库只能引用其他接口库(或 .net 库(。这意味着我所有的ApplicationUser参数和变量都变得IApplicationUser

经过几个小时的更改,我完成了所有构建,但是在运行时出现以下错误:

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

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

我之前已经解决了以下代码的dbcontext问题 http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration (特别是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)));

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

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

I应用用户.cs

public interface IApplicationUser : IUser, IUser<string>
{
     ...
}

应用程序用户.cs

public class ApplicationUser : IdentityUser, IApplicationUser
{
     ...
}

ApplicationDbContext.cs

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>

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

第二次尝试:

@guillaume31的有用链接之后,我尝试了以下内容:

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<>), new InjectionConstructor(typeof(ApplicationDbContext)));

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

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

第三次尝试

container.RegisterType(typeof(IUserStore<>), typeof(UserStore<ApplicationUser>), new InjectionConstructor(typeof(ApplicationDbContext)));

导致此错误:

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

第四次尝试

container.RegisterType(typeof(IUserStore<IApplicationUser>), typeof(UserStore<ApplicationUser>), new InjectionConstructor(typeof(ApplicationDbContext)));

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

无法强制转换类型的对象 'Microsoft.AspNet.Identity.EntityFramework.UserStore 1[Common.Models.Account.ApplicationUser]' to type 'Microsoft.AspNet.Identity.IUserStore 1[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);

新错误为:

类型 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.IUserStore 1[Vero.Common.Verofy.Models.Interfaces.Account.IApplicationUser]。 参数名称:实例

第六次尝试(旁路注射(:

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

IUserStore<IApplicationUser> test = (IUserStore<IApplicationUser>)new UserStore<ApplicationUser>(applicationDbContext);

错误是:

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

总结

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

更新

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

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

这是我一直在使用的

        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());

UserStoreRepository只是

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

同样地

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

当然,您需要注册上下文

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

对于其他事情:

public class ApplicationUserManager : UserManager<IdentityUser>
 public class ApplicationRoleManager : RoleManager<IdentityRole>

我认为您的第一次尝试几乎是正确的,我会尝试将您的 UserStore 包装到包装您的应用程序用户的不同对象

> 基本上,http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registration 中的示例提供了一段代码,该代码添加了不应该存在的依赖项。

解决方案是改变这一点:

Provider = new CookieAuthenticationProvider
{
    // Enables the application to validate the security stamp when the user logs in.
    // This is a security feature which is used when you change a password or add an external login to your account.  
    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30),
        regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
}

对此:

Provider = new CookieAuthenticationProvider
{
    // Enables the application to validate the security stamp when the user logs in.
    // This is a security feature which is used when you change a password or add an external login to your account.  
    OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
        validateInterval: TimeSpan.FromMinutes(30),
        regenerateIdentity: (manager, user) => manager.CreateIdentityAsync(user, DefaultAuthenticationTypes.ApplicationCookie))
}

并从ApplicationUser中删除GenerateUserIdentityAsync方法。

这基本上将调用从user(usermanager)翻转到usermanager(user),并且无需在 IApplication用户界面中引用应用程序用户!

然后,我能够在一个库中拥有ApplicationUser类,将接口放在另一个库中,并且应用程序中只有与特定应用程序相关的类。

相关内容

  • 没有找到相关文章