为什么这违反了类型参数的限制' TUser'?

时间:2016-09-17 15:42:31

标签: asp.net-core asp.net-identity asp.net-identity-3

我正在尝试使用以下内容自定义asp.net身份实体:

public class User : IdentityUser<string, UserClaim, UserRole, UserLogin>
public class UserClaim : IdentityUserClaim<string>
public class UserLogin : IdentityUserLogin<string>
public class UserRole : IdentityUserRole<string>
public class UserToken : IdentityUserToken<string>
public class Role : IdentityRole<string, UserRole, RoleClaim>
public class RoleClaim : IdentityRoleClaim<string>

然后我创建了一个DbContext类,如下所示

public class AppDbContext : IdentityDbContext<User, Role, string, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>

然后使用

配置它们
services
    .AddIdentity<User, Role>()
    .AddEntityFrameworkStores<AppDbContext>()
    .AddDefaultTokenProviders();

但我也试过

.AddEntityFrameworkStores<AppDbContext, string>()

我在互联网上阅读了很多博客文章,例如this,但大多数博客都要针对密钥的数据类型进行更改,例如int或{{1 }}。在我的情况下,我没有更改Guid的默认密钥数据类型。

我在所有这些情况下编译都没问题,但在运行

时会抛出错误
  

System.TypeLoadException   GenericArguments [0],&#39; MyIdentity.Entities.User&#39;,on   &#39; Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`8 [TUSER,TRole,TContext,TKEY的,TUserClaim,TUserRole,TUserLogin,TUserToken]&#39;   违反了类型参数约束&#39; TUser&#39;。

     

在System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle句柄,   IntPtr * pInst,int numGenericArgs,ObjectHandleOnStack type)at   System.RuntimeTypeHandle.Instantiate(Type [] inst)at   System.RuntimeType.MakeGenericType(Type [] instantiation)

如果我添加自定义string类,如this post

中所述
UserStore

出现编译错误

  

CS0311类型&#39; MyIdentity.Entities.Role&#39;不能用作类型   参数&#39; TRole&#39;在通用类型或方法&#39; UserStore&#39;。没有隐式引用转换   &#39; MyIdentity.Entities.Role&#39;至   &#39;&Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole GT;&#39;

我做错了什么?

3 个答案:

答案 0 :(得分:5)

我遇到了这个问题,我发现了这个问题:"When you are customizing ASP.NET Core Identity, you should not use AddEntityFrameworkStores anymore." 你应该实施你的:

public class ApplicationRoleManager:  RoleManager<Role>
public class ApplicationRoleStore :  RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>
public class ApplicationSignInManager :  SignInManager<User>
public class ApplicationUserManager : UserManager<User>
public class ApplicationUserStore : UserStore<User, Role, ApplicationDbContext, int, UserClaim, UserRole, UserLogin, UserToken, RoleClaim>

然后将内置服务重定向到您的自定义服务(Startup.cs):

services.AddScoped<UserStore<User, Role, ApplicationDbContext, int, UserClaim, UserRole, UserLogin, UserToken, RoleClaim>, ApplicationUserStore> ();
services.AddScoped<UserManager<User>, ApplicationUserManager>();
services.AddScoped<RoleManager<Role>, ApplicationRoleManager>();
services.AddScoped<SignInManager<User>, ApplicationSignInManager>();
services.AddScoped<RoleStore<Role, ApplicationDbContext, int, UserRole, RoleClaim>, ApplicationRoleStore>();
services.AddScoped<IEmailSender, AuthMessageSender>();
services.AddScoped<ISmsSender, AuthMessageSender>();

然后介绍您的自定义服务:

services.AddIdentity<User, Role>(identityOptions =>
{
 // ...
 }).AddUserStore<ApplicationUserStore>()
   .AddUserManager<ApplicationUserManager>()
   .AddRoleStore<ApplicationRoleStore>()
   .AddRoleManager<ApplicationRoleManager>()
   .AddSignInManager<ApplicationSignInManager>()
   // You **cannot** use .AddEntityFrameworkStores() when you customize everything
   //.AddEntityFrameworkStores<ApplicationDbContext, int>()
   .AddDefaultTokenProviders();

答案 1 :(得分:4)

  • According to MSDNUserStore<TUser>的约束为TUser : IdentityUser
  • Also according to MSDNIdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
  • 根据您的声明,User : IdentityUser<string, UserClaim, UserRole, UserLogin>

长名称很容易错过,因此请将IdentityUser别名DIdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>作为B。现在,上述内容可以重申为:

  • TUser : DTUser必须是一种D
  • D : BD是一种B
  • User : B(您的User通常是一种B,但根据需要不具体D

答案 2 :(得分:1)

问题在于RoleClaim必须是IdentityRoleClaim<TKey>

类型
 where TRole : IdentityRole<TKey, TUserRole, IdentityRoleClaim<TKey>>

而不是TRoleClaim

where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>

It's reported here as a bug