Asp.net-Core

為什麼這違反了類型參數“TUser”的約束?

  • January 26, 2021

我正在嘗試使用以下實體自定義 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>()

我在網際網路上閱讀了許多部落格文章,例如這樣,但其中大多數必須處理鍵的數據類型更改,例如 tointGuid. 在我的情況下,我沒有將預設鍵數據類型從string.

在所有這些情況下,編譯都可以,但是在執行時會引發錯誤

System.TypeLoadException GenericArguments

$$ 0 $$,‘MyIdentity.Entities.User’,在’Microsoft.AspNetCore.Identity.EntityFrameworkCore.UserStore`8$$ TUser,TRole,TContext,TKey,TUserClaim,TUserRole,TUserLogin,TUserToken $$’ 違反了類型參數 ‘TUser’ 的約束。 在 System.RuntimeTypeHandle.Instantiate(RuntimeTypeHandle 句柄,IntPtr* pInst,int numGenericArgs,ObjectHandleOnStack 類型)在 System.RuntimeTypeHandle.Instantiate(類型

$$ $$inst) 在 System.RuntimeType.MakeGenericType(Type$$ $$實例化)

如果我像這篇文章UserStore中解釋的那樣添加一個自定義類

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

出現編譯錯誤,說明

CS0311 類型“MyIdentity.Entities.Role”不能用作泛型類型或方法“UserStore”中的類型參數“TRole”。沒有從“MyIdentity.Entities.Role”到“Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole>”的隱式引用轉換

我做錯了什麼?

  • 根據 MSDN,約束UserStore<TUser>TUser : IdentityUser
  • 同樣根據IdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>MSDN ,.
  • 根據您的聲明,User : IdentityUser<string, UserClaim, UserRole, UserLogin>.

長名字很容易被忽略,所以讓我們別名IdentityUserasDIdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>as B。現在可以將上面的內容重新表述為:

  • TUser : D(aTUser必須是一種D
  • D : BD是一種B
  • User : B(根據需要,您UserB一般的但不是D具體的)

我遇到了這個問題,我發現:“當您自定義 ASP.NET Core 標識時,您不應再使用 AddEntityFrameworkStores。”
你應該實現你的:

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

引用自:https://stackoverflow.com/questions/39548668