目录
- public interface IDomainEvent:INotification
- {
- }
其中INotification来自MediatR:
- namespace MediatR
- {
- //
- // 摘要:
- // Marker interface to represent a notification
- public interface INotification
- {
- }
- }
所有的领域事件都应该集成该接口。
- public interface IDomainEventHandler<TDomainEvent>:INotificationHandler<TDomainEvent>
- where TDomainEvent:IDomainEvent
- {
- //这里我们使用了INotificationHandler的Handle方法来作为处理方法的定义
- //Task Handle(TDomainEvent domainEvent, CancellationToken cancellationToken);
- }
领域事件处理接口是泛型接口,其实例化成员只能处理特定的领域事件。因为基类接口有Handler方法,所有不用再重复定义。
领域事件是为实体服务的,所以实体里面要有领域事件的处理办法。在抽象类Entity表示如下:
- #region
- private List
_domainEvents=new List(); - public IReadOnlyCollection
DomainEvents => _domainEvents?.AsReadOnly(); -
- public void AddDomainEvent(IDomainEvent eventItem)
- {
- _domainEvents = _domainEvents ?? new List
(); - _domainEvents.Add(eventItem);
- }
-
- public void RemoveDomainEvent(IDomainEvent eventItem)
- {
- _domainEvents?.Remove(eventItem);
- }
-
- public void ClearDomainEvents()
- {
- _domainEvents?.Clear();
- }
- #endregion
主要是定义了一个领域事件List,并配有三个方法来管理这个集合。
当我们通过 仓储保存实体时:
- public class EFContext:DbContext, IUnitOfWork,ITransaction
- {
- ....
- public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
- {
- var result = await base.SaveChangesAsync(cancellationToken);
- await _mediator.DispatchDomainEventsAsync(this);
- return true;
- }
- }
会调用DispatchDomainEventAsync,重点关注这个函数:
- public static class MediatorExtension
- {
- public static async Task DispatchDomainEventsAsync(this IMediator mediator, DbContext ctx)
- {
- var domainEntities = ctx.ChangeTracker
- .Entries
() - .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any());
-
- var domainEvents = domainEntities
- .SelectMany(x => x.Entity.DomainEvents)
- .ToList();
-
- domainEntities.ToList()
- .ForEach(entity => entity.Entity.ClearDomainEvents());
-
- foreach (var domainEvent in domainEvents)
- await mediator.Publish(domainEvent);
- }
- }
这是一个扩展方法,获取所有跟踪的实体对象,然后将所有的实体对象放入list,放入后先清楚原来实体中的领域事件,然后发送出去。这样就会被响应。也就是,在保存实体的时候才会触发事件响应。
1.由领域模型内部创建领域事件
2.由专有的领域事件处理类来处理领域事件
3.根据实际情况来决定是否在同一事务中处理