0

我正在尝试实现 UserStore,但我也想实现 UserEmailStore 和 UserLockoutStore 等。我注意到所有 User*Store 都基于 UserStore,没问题。但我查看了 UserManager,发现对我来说很奇怪。您可以向 UserManager 注入多种类型的存储,但始终只能注入一种。但是 UserManager 可以根据您注入的类型与所有这些一起使用。

来自 UserManager 的 Fox 示例方法 GetLockoutEndDateAsync

public virtual async Task<DateTimeOffset?> GetLockoutEndDateAsync(TUser user)
{
  this.ThrowIfDisposed();
  IUserLockoutStore<TUser> userLockoutStore = this.GetUserLockoutStore();
  if ((object) user == null)
    throw new ArgumentNullException("user");
  TUser user1 = user;
  CancellationToken cancellationToken = this.CancellationToken;
  return await userLockoutStore.GetLockoutEndDateAsync(user1, cancellationToken);
}

方法this.GetUserLockoutStore看起来像这样

internal IUserLockoutStore<TUser> GetUserLockoutStore()
{
  IUserLockoutStore<TUser> userLockoutStore = this.Store as IUserLockoutStore<TUser>;
  if (userLockoutStore != null)
    return userLockoutStore;
  throw new NotSupportedException(Resources.StoreNotIUserLockoutStore);
}

还有其他方法,例如

  • 获取电子邮件商店
  • 获取电话号码存储
  • GetClaimStore
  • 获取登录商店
  • ...

所以这意味着商店必须基于您要使用的正确界面。

我的问题是,如何处理这个问题?我应该基于所有可能的 User*Store 接口实现一个商店吗?或者你能建议另一种解决方案吗?

提前致谢

4

1 回答 1

3

是的,在单个商店中将所需的接口实现为“功能”是一种直接的方法,这也是实现 ASP.NET Core Identity EF Core 提供程序的方式(请参见 此处

/// <summary>
/// Represents a new instance of a persistence store for the specified user and role types.
/// </summary>
/// <typeparam name="TUser">The type representing a user.</typeparam>
/// <typeparam name="TRole">The type representing a role.</typeparam>
/// <typeparam name="TContext">The type of the data context class used to access the store.</typeparam>
/// <typeparam name="TKey">The type of the primary key for a role.</typeparam>
/// <typeparam name="TUserClaim">The type representing a claim.</typeparam>
/// <typeparam name="TUserRole">The type representing a user role.</typeparam>
/// <typeparam name="TUserLogin">The type representing a user external login.</typeparam>
/// <typeparam name="TUserToken">The type representing a user token.</typeparam>
/// <typeparam name="TRoleClaim">The type representing a role claim.</typeparam>
public abstract class UserStore<TUser, TRole, TContext, TKey, TUserClaim, TUserRole, TUserLogin, TUserToken, TRoleClaim> :
    IUserLoginStore<TUser>,
    IUserRoleStore<TUser>,
    IUserClaimStore<TUser>,
    IUserPasswordStore<TUser>,
    IUserSecurityStampStore<TUser>,
    IUserEmailStore<TUser>,
    IUserLockoutStore<TUser>,
    IUserPhoneNumberStore<TUser>,
    IQueryableUserStore<TUser>,
    IUserTwoFactorStore<TUser>,
    IUserAuthenticationTokenStore<TUser>
    where TUser : IdentityUser<TKey, TUserClaim, TUserRole, TUserLogin>
    where TRole : IdentityRole<TKey, TUserRole, TRoleClaim>
    where TContext : DbContext
    where TKey : IEquatable<TKey>
    where TUserClaim : IdentityUserClaim<TKey>
    where TUserRole : IdentityUserRole<TKey>
    where TUserLogin : IdentityUserLogin<TKey>
    where TUserToken : IdentityUserToken<TKey>
    where TRoleClaim : IdentityRoleClaim<TKey>
{
}

您只需要实现您将要支持的接口,而将其他接口排除在外。

如果由于某种原因(单一职责原则)这是不可能的(即,因为您需要使用完全不同类型的数据库或某些 web 服务或 Active Directory),那么您可以实现单独的存储并使用外观模式来环绕它并将您的个人商店注入外观并注入外观。

但它需要更多的工作,并且需要更多的 DI 设置来完成它。但可行。

于 2017-02-16T11:56:53.737 回答