【发布时间】:2019-07-31 01:27:38
【问题描述】:
我一直在从事一个使用 DDD 架构的新文档管理项目。我是 DDD 和事件驱动设计的新手,所以这是一次学习经历。
我的应用程序结构如下:
- MyProgram.Domain
- MyProgram.Infrastructure
- MyProgram.App
- MyProgram.WebApi
Domain 拥有我所有的领域逻辑,基础设施是持久性,应用程序主要是命令和处理程序,而 webapi 就是 webapi。
现在我正在努力实现用户授权,并且目前我决定使用授权处理程序,该处理程序将在执行命令或查询之前进行权限检查。我认为这给了我很好的灵活性来执行复杂的基于资源的授权,因为我的许多权限将取决于某个实体的当前状态。
到目前为止,这是可行的,我已经在我的应用程序层中实现了授权,将大部分用户特定信息排除在我的域模型之外。
现在,我要解决的问题是如何最好地将用户信息包含在我的域事件中,这些事件是从我的域类中引发的。
例如,我有一定的聚合,比如说它的文档,文档有一定的审批流程。因此,当文档获得批准时,我想引发一个域事件,例如
public class DocumentApproved : IDomainEvent
{
public DocumentApproved (Package package)
{
DocumentId= document.Id;
Timestamp = DateTime.Now;
}
public Guid Id { get; }
public Guid UserId { get; }
public DateTime Timestamp { get; }
public Guid PackageId { get; }
}
系统需要可审计,因此我计划将域事件用作审计跟踪以及引起副作用或向其他系统发送消息的机制。
Document 实体可能有一个看起来像这样的方法:
public void Approve()
{
State = State.Approve(this);
ApprovalRevision.Next();
Events.Add(new DocumentApproved(this));
}
我的问题
我想在几乎每个适用的域事件中都包含 UserId,但我想不出如何做到这一点,而不必让 userId 成为我的域实体上每个相关方法的参数,这意味着它们只是为了创建领域事件的一个参数,因为所有授权类型的活动都将在应用层发生。
这是解决此问题的合理方法,还是我应该尝试以不同的方式捕获用户活动,例如我的请求管道,并将这些活动与域事件分开?这对我来说听起来不太对劲。将 userId 作为可能导致域事件的每个方法的参数确实不是什么问题,但这似乎只会给每个域实体签名添加混乱。
为了引发我的域事件,我正在做类似于here 建议的事情,其中实体有一个 DomainEvents 集合,它们在保存实体之前通过 MediatR 发布。
【问题讨论】:
标签: c# dns domain-driven-design mediatr