从另一个项目继承(?)IdentityUser [英] Inherit (?) IdentityUser from another project

查看:54
本文介绍了从另一个项目继承(?)IdentityUser的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的解决方案中有多个项目,都是.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 on IdentityUser. 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆