【问题标题】:UserManager used with different stores (UserStore, UserEmailStore, UserClaimStore, UserLockoutStore etc.)UserManager 用于不同的商店(UserStore、UserEmailStore、UserClaimStore、UserLockoutStore 等)
【发布时间】:2017-07-05 10:47:44
【问题描述】:

我正在尝试实现 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);
}

还有其他方法,比如

  • GetEmailStore
  • GetPhoneNumberStore
  • GetClaimStore
  • 获取LoginStore
  • ...

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

我的问题是,如何处理这个问题?我应该基于所有可能的 User*Store 接口实现一个商店吗?或者您能提出其他解决方案吗?

提前致谢

【问题讨论】:

    标签: c# asp.net-core .net-core usermanager


    【解决方案1】:

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

    /// <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 设置来完成。但可行。

    【讨论】:

    • 这正是我需要的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2016-07-31
    • 2017-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-15
    • 2015-08-07
    相关资源
    最近更新 更多