从另一个项目继承(?)IdentityUser [英] Inherit (?) IdentityUser from another project
问题描述
我的解决方案中有多个项目,都是.NET Core 3.1.其中之一是我的核心项目(" A Project "),其中我只有基本模型类,没有方法或数据库访问权限.出于演示目的,以下是我的 Address.cs
和 User.cs
文件的简化版本:
I have multiple projects in my solution, all .NET Core 3.1. One of them is my core project ("A Project") where I just have basic model classes with no methods or database access. For demonstration purposes, below are simplified versions of my Address.cs
and User.cs
files:
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;}
}
在另一个项目(" B项目")中,我将构建实际功能.该项目已经具有带有 ApplicationUser
类的ASP.NET Core Identity设置,该类从 IdentityUser
派生并添加了一些自定义属性.
In another project ("B Project"), I will be building the actual functionality. This project already has ASP.NET Core Identity setup with an ApplicationUser
class, which derives from IdentityUser
and adds some custom properties.
这是我遇到问题的地方.必须将 Address.User
属性设置为 ApplicationUser
的实例,但是 ApplicationUser
位于 B项目中
This is where I run into my problem. The Address.User
property has to be set to an instance of ApplicationUser
, but ApplicationUser
lives in the B Project.
很明显,我没有在我的项目中将ASP.NET Core Identity设置为依赖项,因此无法将 ApplicationUser
类移入该类中项目.此外,由于 ApplicationUser
并非源自 User
,因此我无法将 ApplicationUser
分配给 Address.User
属性.
Obviously, I don't have ASP.NET Core Identity set up as a dependency within my A Project, so I can't move the ApplicationUser
class into that project. Further, I cannot assign the ApplicationUser
to the Address.User
property since ApplicationUser
doesn’t derive from User
.
经过一些研究,我发现了两个不同的建议.一个建议是为ASP.NET Core Identity组件使用一个单独的项目,然后在我的 B项目中与我的 A项目一起引用它.另一个灵魂建议创建我自己的 UserStore
.
Having done some research, I found a couple of different suggestions. One proposal is to use a separate project for the ASP.NET Core Identity components and then reference it alongside my A Project from within my B Project. Another soul suggested creating my own UserStore
.
我不希望我的项目依赖任何东西.但是我没有足够的经验来决定哪种方案更适合我的情况.
I don't want my A Project to be dependent upon anything. But I don’t have enough experience to decide what option is preferable for my scenario.
推荐答案
我以前肯定已经把自己画在这个特定的角落了!
I have definitely painted myself into this particular corner before!
您可以采取几种策略来解决此问题,包括您列出的两种.但是,我建议的方法是使用接口.
There are a few strategies you can take to resolve this, including the two you listed. The approach I‘d recommend, however, is to use interfaces.
您将拥有一个 IUser
interface ,而不是拥有一个具体的 User
class 请参考项目A 中的模型.然后,您将 IUser
接口应用于您的 ApplicationUser
类.这样可以将 ApplicationUser
的实例分配给您的尽管 Address
不了解 ApplicationUser
.
Instead of having a concrete User
class, you’ll instead have an IUser
interface which you’ll reference from the models in Project A. You’ll then apply the IUser
interface to your ApplicationUser
class. This will allow instances of ApplicationUser
to be assigned to your e.g. Address.User
property, despite the fact that Address
isn’t aware of ApplicationUser
.
在项目A 中,您将类更新为以下内容:
In Project A, you’ll update your classes to something like the following:
public class Address
{
public int Id {get;set;}
public string AddressText {get;set;}
public virtual IUser User {get;set;}
}
public interface IUser
{
int UserId {get;set;}
int UserName {get;set;}
ICollection<Address> {get;set;}
}
然后,在项目B 中,将 IUser
接口应用于 ApplicationUser
类,并确保其实现必需的属性:
Then, in Project B, you’ll apply the IUser
interface to your ApplicationUser
class and ensure it implements the required properties:
public class ApplicationUser: IdentityUser, IUser
{
…
public int UserId {get;set;}
public ICollection<Address> {get;set;}
}
注意:您无需实现
UserName
,因为该功能已经在IdentityUser
上实现.当然,如果需要,您总是可以覆盖该属性(例如,添加验证属性).
Note: You don’t need to implement
UserName
, as that’s already been implemented onIdentityUser
. Though, of course, you can always override the property, should the need arise (e.g., to add validation attributes).
限制
当您访问例如 Address.User
属性时,您将只能访问在 IUser
上定义的成员.如果您需要访问在 ApplicationUser
或 IdentityUser
上定义的任何其他成员,则首先需要将 IUser
引用强制转换为ApplicationUser
;例如,
Limitations
When you access e.g., your Address.User
property, you’ll only be able to access the members you defined on IUser
. If you need to access any additional members defined on either ApplicationUser
or IdentityUser
, you will first need to cast your IUser
reference to an ApplicationUser
; e.g.,
var user = address.User as ApplicationUser;
var emailConfirmed = user?.EmailConfirmed?? false;
当然,如果您知道,则需要访问这些成员,您只需确保在您的界面上定义了它们即可,而不必担心.
Of course, if you know you’re going to need access to these members, you can just make sure they’re defined on your interface, and not have to worry about this.
有几点需要注意的注意事项.这些可能不适用于您,但为了完整起见,我想将它们包括在内.
There are a couple of considerations worth being aware of. These may not apply to you, but I want to include them for completeness.
如我的评论中所述,如果您使用O/RM来填充模型(例如Entity Framework(EF)核心),则可能会遇到在单独的程序集中识别接口的具体实现时遇到的问题.可以做到这一点,但肯定会增加您可能不希望面对的复杂性!不过,如果您是手动构建对象图,则不会有问题.
As mentioned in my comment, if you’re using an O/RM to populate your models—such as Entity Framework (EF) Core—you may run into problems identifying a concrete implementation of your interface in a separate assembly. This can be done, but it definitely adds complexity which you may not want to contend with! If you’re manually constructing your object graph, though, this won’t be an issue.
IdentityUser
旨在表示当前经过身份验证的用户,而不是一般用户引用.例如,在一个电子商务应用程序中,构造一个 IdentityUser
来引用每种产品的卖方是没有意义的.显然这里存在重叠,并且使用一个数据源同时提供这两个数据源是可以的.但是,还有一些属性(例如 PasswordHash
或 SecurityStamp
)对于在一般用户模型上进行填充是没有意义的.您最终可能会发现这些需求彼此冲突.
The IdentityUser
is meant to represent the currently authenticated user, not a general user reference. For instance, in an e-commerce app, it doesn’t make sense to construct an IdentityUser
for references to the seller of each product. There is obviously overlap here, and using one data source to feed both is fine. But there are also properties—such as PasswordHash
or SecurityStamp
—which don’t make sense to populate on a general user model. You may eventually find these needs in conflict with one another.
在上述两种情况下,您可能会发现区分 ApplicationUser
和 User
类更加容易.这不是您要的,但是值得考虑.在这种情况下,@ RomanKalinchuk的方法更有意义.虽然,即使那样,您仍然可以通过对每个应用相同的 IUser
接口来统一它们,从而确保它们共享一组核心属性.
In either of the above cases, you may find it easier to differentiate between your ApplicationUser
and your User
classes. That’s not what you asked for, but it’s worth considering. In that case, @RomanKalinchuk‘s approach makes more sense. Though, even then, you can still unify them by applying the same IUser
interface to each, thus ensuring they share a core set of properties.
这篇关于从另一个项目继承(?)IdentityUser的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!