从另一个项目继承 (?) IdentityUser

Kem*_*min 6 c# asp.net-core asp.net-core-identity

我的解决方案中有多个项目,都是 .NET Core 3.1。其中之一是我的核心项目(“ A Project ”),其中我只有基本的模型类,没有方法或数据库访问权限。出于演示目的,以下是 myAddress.cs和User.csfiles 的简化版本:

public class Address 
{
     public int Id {get;set;}
     public string AddressText {get;set;}
     public virtual User User {get;set;}
}

public class User
{
    public int UserId {get;set;}
    public int UserName {get;set;}

    public ICollection<Address> {get;set;}
}
Run Code Online (Sandbox Code Playgroud)

在另一个项目(“ B 项目”)中,我将构建实际的功能。该项目已经设置了带有ApplicationUser类的ASP.NET Core Identity,该类派生自IdentityUser并添加了一些自定义属性。

这就是我遇到问题的地方。该Address.User属性必须设置为 的实例ApplicationUser,但ApplicationUser位于B 项目中。

显然,我没有将 ASP.NET Core Identity 设置为我的A Project 中的依赖项,因此我无法将该ApplicationUser类移到该项目中。此外,我无法将 分配ApplicationUser给该Address.User属性,因为ApplicationUser它不是从User.

做了一些研究后,我发现了一些不同的建议。一个建议是为 ASP.NET Core Identity 组件使用一个单独的项目,然后在我的B Project中将它与我的A Project一起引用。另一个灵魂建议创建我自己的.UserStore

我不希望我的A 项目依赖于任何东西。但是我没有足够的经验来决定哪种选项更适合我的场景。

Jer*_*ney 7

我以前确实把自己画进了这个特殊的角落!

\n

您可以采取一些策略来解决此问题,包括您列出的两种策略。然而,我\xe2\x80\x98d推荐的方法是使用接口。

\n

概括

\n

您\xe2\x80\x99ll没有具体的User 类,而是具有一个IUser 接口,您\xe2\x80\x99ll 从项目 A中的模型中引用该接口。然后,您\xe2\x80\x99 会将接口应用IUser到您的ApplicationUser类中。这将允许将 的实例ApplicationUser分配给您的 egAddress.User属性,尽管事实上Address\xe2\x80\x99不知道ApplicationUser。

\n

例子

\n

在项目 A中,您\xe2\x80\x99 将您的类更新为如下所示:

\n
public class Address \n{\n     public int Id {get;set;}\n     public string AddressText {get;set;}\n     public virtual IUser User {get;set;}\n}\n\npublic interface IUser\n{\n    int UserId {get;set;}\n    int UserName {get;set;}\n    ICollection<Address> {get;set;}\n}\n
Run Code Online (Sandbox Code Playgroud)\n

然后,在项目 B中,您\xe2\x80\x99 将IUser接口应用到您的ApplicationUser类并确保它实现所需的属性:

\n
public class ApplicationUser: IdentityUser, IUser \n{\n  \xe2\x80\xa6 \n  public int UserId {get;set;}\n  public ICollection<Address> {get;set;}\n}\n
Run Code Online (Sandbox Code Playgroud)\n
\n

注意:您不需要实现\xe2\x80\x99s UserName,因为\xe2\x80\x99s 已经在 上实现了IdentityUser。当然,如果需要的话(例如,添加验证属性),您始终可以覆盖该属性。

\n
\n

局限性

\n

当您访问例如您的Address.User属性时,您\xe2\x80\x99将只能访问您在 上定义的成员IUser。如果您需要访问 或 上定义的任何其他成员ApplicationUser,IdentityUser您首先需要将引用IUser转换为ApplicationUser; 例如,

\n
var user = address.User as ApplicationUser;\nvar emailConfirmed = user?.EmailConfirmed?? false;\n
Run Code Online (Sandbox Code Playgroud)\n

当然,如果您知道您\xe2\x80\x99将需要访问这些成员,您只需确保它们\xe2\x80\x99在您的接口上定义即可,而不必担心这一点。

\n

注意事项

\n

有几个注意事项值得注意。这些可能不适用于您,但为了完整性我想将它们包括在内。

\n

操作/管理

\n

正如我在评论中提到的,如果您\xe2\x80\x99使用O/RM来填充您的模型\xe2\x80\x94,例如Entity Framework (EF) Core\xe2\x80\x94,您可能会遇到识别具体实现的问题您的界面位于单独的程序集中。这是可以做到的,但它肯定会增加您可能不想面对的复杂性!不过,如果您手动构建对象图,这将不会成为问题。

\n

身份与用户模型

\n

它IdentityUser代表当前经过身份验证的用户,而不是一般用户引用。例如,在电子商务应用程序中,构建IdentityUser对每个产品的卖家的引用是没有意义的。这里显然存在重叠,使用一个数据源来同时提供两个数据源就可以了。但也有属性\xe2\x80\x94如PasswordHash或SecurityStamp\xe2\x80\x94,这些属性在一般用户模型上填充时没有意义。您最终可能会发现这些需求相互冲突。

\n
\n

在上述任何一种情况下,您可能会发现更容易区分您ApplicationUser和您的User班级。那\xe2\x80\x99不是你所要求的,但它\xe2\x80\x99值得考虑。在这种情况下,@RomanKalinchuk\xe2\x80\x98s 方法更有意义。尽管如此,即使如此,您仍然可以通过应用相同的方法来统一它们IUser每个应用相同的接口来统一它们,从而确保它们共享一组核心属性。

\n

  • 显然,如果您之前确实经历过这条道路,您也会知道我针对单独的域和项目使用 webapi 和 JWT 的方向。我接受了这个答案,因为它实际上通过消除我正在考虑的其他可能性来解决我的问题。赞成它,因为我相信很多人会节省遇到这个问题的时间,并鼓掌只是因为这是这里的一个新功能:)非常感谢。 (2认同)