2016-09-17 139 views
3

我想定製asp.net身份實體下面的:爲什麼這違反了類型參數'TUser'的約束?

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,但是其中大部分都必須處理密鑰數據類型的變化,比如intGuid。在我的情況下,我不會更改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表示,整數numGenericArgs,ObjectHandleOnStack型)在 System.RuntimeTypeHandle.Instantiate(類型[]研究所)在 System.RuntimeType.MakeGenericType(類型[]實例化)

如果我添加定製UserStore類像this post

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

解釋編譯錯誤出現說

CS0311類型「MyIdentity.Entities.Role」不能被用作在通用類型或方法 類型參數「TRole」「UserStore」。有一個從 「MyIdentity.Entities.Role」的隱式引用轉換 「Microsoft.AspNetCore.Identity.EntityFrameworkCore.IdentityRole>」

我做錯了嗎?

+1

你的'用戶'類有一個默認構造函數? –

+0

@TheodorosChatzigiannakis:是的。我剛剛檢查過。 '公共用戶():base()' – Lorenzo

回答

4
  • According to MSDNUserStore<TUser>的約束條件是TUser : IdentityUser
  • Also according to MSDNIdentityUser : IdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>
  • 根據你的申報,User : IdentityUser<string, UserClaim, UserRole, UserLogin>

長的名字可以很容易錯過,讓我們的別名IdentityUserDIdentityUser<string, IdentityUserLogin, IdentityUserRole, IdentityUserClaim>B。現在,上面可以重新表述爲:

  • TUser : D(一TUser必須是一種D
  • D : BD是一種B
  • User : B(您User是一種B一般而不是一種D具體,根據需要)
+0

你絕對是對的Theodoros。我試圖刪除長的聲明,一切正常。感謝您的建議。 – Lorenzo

1

問題是在這裏RoleClaim必須是TRoleClaim

where TRole : IdentityRole<TKey, TUserRole, TRoleClaim> 

It's reported here as a bug類型的IdentityRoleClaim<TKey>

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

代替。

3

我面對這個問題,我發現這一點:"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(); 
相關問題