• 微服务实战之领域事件


    目录

    1.定义领域事件接口

    2.领域事件处理接口

    3.领域事件在实体的处理

    4.小结


    1.定义领域事件接口

    1. public interface IDomainEvent:INotification
    2. {
    3. }

    其中INotification来自MediatR:

    1. namespace MediatR
    2. {
    3. //
    4. // 摘要:
    5. // Marker interface to represent a notification
    6. public interface INotification
    7. {
    8. }
    9. }

    所有的领域事件都应该集成该接口。

    2.领域事件处理接口

    1. public interface IDomainEventHandler<TDomainEvent>:INotificationHandler<TDomainEvent>
    2. where TDomainEvent:IDomainEvent
    3. {
    4. //这里我们使用了INotificationHandler的Handle方法来作为处理方法的定义
    5. //Task Handle(TDomainEvent domainEvent, CancellationToken cancellationToken);
    6. }

    领域事件处理接口是泛型接口,其实例化成员只能处理特定的领域事件。因为基类接口有Handler方法,所有不用再重复定义。

    3.领域事件在实体的处理

    领域事件是为实体服务的,所以实体里面要有领域事件的处理办法。在抽象类Entity表示如下:

    1. #region
    2. private List _domainEvents=new List();
    3. public IReadOnlyCollection DomainEvents => _domainEvents?.AsReadOnly();
    4. public void AddDomainEvent(IDomainEvent eventItem)
    5. {
    6. _domainEvents = _domainEvents ?? new List();
    7. _domainEvents.Add(eventItem);
    8. }
    9. public void RemoveDomainEvent(IDomainEvent eventItem)
    10. {
    11. _domainEvents?.Remove(eventItem);
    12. }
    13. public void ClearDomainEvents()
    14. {
    15. _domainEvents?.Clear();
    16. }
    17. #endregion

    主要是定义了一个领域事件List,并配有三个方法来管理这个集合。

    当我们通过 仓储保存实体时:

    1. public class EFContext:DbContext, IUnitOfWork,ITransaction
    2. {
    3. ....
    4. public async Task<bool> SaveEntitiesAsync(CancellationToken cancellationToken = default)
    5. {
    6. var result = await base.SaveChangesAsync(cancellationToken);
    7. await _mediator.DispatchDomainEventsAsync(this);
    8. return true;
    9. }
    10. }

    会调用DispatchDomainEventAsync,重点关注这个函数:

    1. public static class MediatorExtension
    2. {
    3. public static async Task DispatchDomainEventsAsync(this IMediator mediator, DbContext ctx)
    4. {
    5. var domainEntities = ctx.ChangeTracker
    6. .Entries()
    7. .Where(x => x.Entity.DomainEvents != null && x.Entity.DomainEvents.Any());
    8. var domainEvents = domainEntities
    9. .SelectMany(x => x.Entity.DomainEvents)
    10. .ToList();
    11. domainEntities.ToList()
    12. .ForEach(entity => entity.Entity.ClearDomainEvents());
    13. foreach (var domainEvent in domainEvents)
    14. await mediator.Publish(domainEvent);
    15. }
    16. }

    这是一个扩展方法,获取所有跟踪的实体对象,然后将所有的实体对象放入list,放入后先清楚原来实体中的领域事件,然后发送出去。这样就会被响应。也就是,在保存实体的时候才会触发事件响应。

    4.小结

    1.由领域模型内部创建领域事件

    2.由专有的领域事件处理类来处理领域事件

    3.根据实际情况来决定是否在同一事务中处理

  • 相关阅读:
    leetcode做题笔记179. 最大数
    快速复现 实现 facenet-pytorch 人脸识别 windows上 使用cpu实现 人脸对比
    【操作系统】内存管理(二)—— 程序运行的基本过程和要求
    08-图8 How Long Does It Take
    字符检测专题第一期:OCR技术工业应用浅谈
    ros develop 相关
    Educational Codeforces Round 136 (Rated for Div. 2) 补题题解 (A、B)
    MySQL 更新表的记录
    学网络安全可以参考什么方向?该怎么学?
    【Java|golang】658. 找到 K 个最接近的元素
  • 原文地址:https://blog.csdn.net/q__y__L/article/details/125990518