为什么这违反了类型参数 'TUser' 的约束?
Why this violates the constraint of type parameter 'TUser'?
我正在尝试使用以下内容自定义 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 class,如下所示
public class AppDbContext : IdentityDbContext<User, Role, string, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
然后用
配置这些
services
.AddIdentity<User, Role>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
但我也尝试过
.AddEntityFrameworkStores<AppDbContext, string>()
我在互联网上阅读了很多博文,例如 ,但其中大多数都必须处理键的数据类型更改,例如 int
或 Guid
。就我而言,我没有更改 string
.
中的默认键数据类型
我在所有这些情况下都可以编译,但在 运行
时会抛出错误
System.TypeLoadException
GenericArguments[0],'MyIdentity.Entities.User', on
'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`8[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken]'
violates the constraint of type parameter 'TUser'.
at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle,
IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type) at
System.RuntimeTypeHandle.Instantiate(Type[] inst) at
System.RuntimeType.MakeGenericType(Type[] instantiation)
如果我添加自定义的 UserStore
class,如
中所述
public class UserStore : UserStore<User, Role, AppDbContext, string, UserClaim, UserRole, UserLogin, UserToken>
出现编译错误,提示
CS0311 The type 'MyIdentity.Entities.Role' cannot be used as type
parameter 'TRole' in the generic type or method 'UserStore'. There is no implicit reference conversion from
'MyIdentity.Entities.Role' to
'Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole>'
我做错了什么?
- According to MSDN,
UserStore<TUser>
的约束是 TUser : IdentityUser
。
- Also according to MSDN,
IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
.
- 根据您的声明,
User : IdentityUser<string, UserClaim, UserRole, UserLogin>
。
长名字很容易漏掉,所以让我们将 IdentityUser
别名为 D
,将 IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
别名为 B
。现在上面可以重述为:
TUser : D
(一个TUser
一定是D
的一种)
D : B
(D
是B
的一种)
User : B
(您的 User
是一般的 B
的一种,但不是特定的 D
的一种,根据需要)
问题出在这里RoleClaim
必须是IdentityRoleClaim<TKey>
类型
where TRole : IdentityRole<TKey, TUserRole, IdentityRoleClaim<TKey>>
而不是TRoleClaim
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
我遇到了这个问题,我发现了这个:"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();
我正在尝试使用以下内容自定义 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 class,如下所示
public class AppDbContext : IdentityDbContext<User, Role, string, UserClaim, UserRole, UserLogin, RoleClaim, UserToken>
然后用
配置这些services
.AddIdentity<User, Role>()
.AddEntityFrameworkStores<AppDbContext>()
.AddDefaultTokenProviders();
但我也尝试过
.AddEntityFrameworkStores<AppDbContext, string>()
我在互联网上阅读了很多博文,例如 int
或 Guid
。就我而言,我没有更改 string
.
我在所有这些情况下都可以编译,但在 运行
时会抛出错误System.TypeLoadException GenericArguments[0],'MyIdentity.Entities.User', on 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`8[TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken]' violates the constraint of type parameter 'TUser'.
at System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle handle, IntPtr* pInst, int numGenericArgs, ObjectHandleOnStack type) at System.RuntimeTypeHandle.Instantiate(Type[] inst) at System.RuntimeType.MakeGenericType(Type[] instantiation)
如果我添加自定义的 UserStore
class,如
public class UserStore : UserStore<User, Role, AppDbContext, string, UserClaim, UserRole, UserLogin, UserToken>
出现编译错误,提示
CS0311 The type 'MyIdentity.Entities.Role' cannot be used as type parameter 'TRole' in the generic type or method 'UserStore'. There is no implicit reference conversion from 'MyIdentity.Entities.Role' to 'Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole>'
我做错了什么?
- According to MSDN,
UserStore<TUser>
的约束是TUser : IdentityUser
。 - Also according to MSDN,
IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
. - 根据您的声明,
User : IdentityUser<string, UserClaim, UserRole, UserLogin>
。
长名字很容易漏掉,所以让我们将 IdentityUser
别名为 D
,将 IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
别名为 B
。现在上面可以重述为:
TUser : D
(一个TUser
一定是D
的一种)D : B
(D
是B
的一种)User : B
(您的User
是一般的B
的一种,但不是特定的D
的一种,根据需要)
问题出在这里RoleClaim
必须是IdentityRoleClaim<TKey>
where TRole : IdentityRole<TKey, TUserRole, IdentityRoleClaim<TKey>>
而不是TRoleClaim
where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
我遇到了这个问题,我发现了这个:"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();