Tom*_*Tom 5 .net c# domain-driven-design asp.net-identity clean-architecture
我正在使用Jason Taylor Clean Architecture 模板创建一个新的 Web 应用程序。我的应用程序必须支持帖子和用户实体,并且这些实体是相关的。一个用户可以创建多个帖子。
现在我想实现这个用户实体,以便使用我的应用程序的人可以使用这些用户登录。通常我只会使用 ASP.NET Core Identity,但由于我需要在域项目中引用该引用,并且该项目应该独立于任何框架,所以我无法这样做。
这种情况我该怎么办?
如果您使用唯一标识符(例如 GUID、用户名、电子邮件等)引用某个域实体中的用户实体,为什么您的域模型中会有框架依赖项?
只是不要使用框架层中的某些身份类作为类成员(字段),而是使用原始类型(例如字符串),或者更好的是,使用一些自定义值对象类来代替我提到的用户身份唯一标识符。例如,您可以将其称为UserId。
这样,您就已经将身份框架(可以被视为基础设施层的一部分)与域层完全解耦。
例如,如果您有一个需要了解客户(或买家)的Order域模型实体,您不使用身份层中的ApplicationUser类,而是仅使用独立于框架的用户 ID 类型UserId。
您可以查看Microsoft eshopOnWeb以了解如何完成此操作的一些示例。
此示例显示了Order 域实体:
public class Order : BaseEntity, IAggregateRoot
{
private Order()
{
// required by EF
}
public Order(string buyerId, Address shipToAddress, List<OrderItem> items)
{
Guard.Against.NullOrEmpty(buyerId, nameof(buyerId));
Guard.Against.Null(shipToAddress, nameof(shipToAddress));
Guard.Against.Null(items, nameof(items));
BuyerId = buyerId;
ShipToAddress = shipToAddress;
_orderItems = items;
}
public string BuyerId { get; private set; }
public DateTimeOffset OrderDate { get; private set; } = DateTimeOffset.Now;
public Address ShipToAddress { get; private set; }
// DDD Patterns comment
// Using a private collection field, better for DDD Aggregate's encapsulation
// so OrderItems cannot be added from "outside the AggregateRoot" directly to the collection,
// but only through the method Order.AddOrderItem() which includes behavior.
private readonly List<OrderItem> _orderItems = new List<OrderItem>();
// Using List<>.AsReadOnly()
// This will create a read only wrapper around the private list so is protected against "external updates".
// It's much cheaper than .ToList() because it will not have to copy all items in a new collection. (Just one heap alloc for the wrapper instance)
//https://msdn.microsoft.com/en-us/library/e78dcd75(v=vs.110).aspx
public IReadOnlyCollection<OrderItem> OrderItems => _orderItems.AsReadOnly();
public decimal Total()
{
var total = 0m;
foreach (var item in _orderItems)
{
total += item.UnitPrice * item.Units;
}
return total;
}
}
Run Code Online (Sandbox Code Playgroud)
在这里您可以看到,对用户的引用只是通过字符串引用,这里是BuyerId 属性,它不会将任何身份框架依赖项引入域层。如果应用程序中的某个点需要用户身份对象,则可以从订单实体查询该买家 ID,并且可以从域层外部的基础设施请求用户身份对象。
在Order实体中应用的相同模式也可以应用于您的Post 实体,例如,通过引用用户的AuthorId属性之类的内容,该属性可以是域层中定义的某个字符串或自定义类(值对象)。
| 归档时间: |
|
| 查看次数: |
2852 次 |
| 最近记录: |