MediatR 中介模式
使用MediatR完成基于内存级别的消息发布订阅
在微服务架构中领域驱动模型中处理领域事件的相关操作
在区分好领域模型后,就拿代码中来说嘛,用户领域中添加用户操作可能或存在跟用户相关的一些领域事件,在添加用户的时候会执行相关的领域事件
首先需要添加nuget包 MediatR
MediatR中有几个对象:IRequest,IRequestHandler,INotificationHandler
具体用法可以看下MediatR github
领域模型需要继承Entity,里面封装了 领域事件的相关操作
public abstract class Entity { int? _requestedHashCode; int _Id; public virtual int Id { get { return _Id; } protected set { _Id = value; } } private List<INotification> _domainEvents; public IReadOnlyCollection<INotification> DomainEvents => _domainEvents?.AsReadOnly(); public void AddDomainEvent(INotification eventItem) { _domainEvents = _domainEvents ?? new List<INotification>(); _domainEvents.Add(eventItem); } public void RemoveDomainEvent(INotification eventItem) { _domainEvents?.Remove(eventItem); } public void ClearDomainEvents() { _domainEvents?.Clear(); } public bool IsTransient() { return this.Id == default(Int32); } public override bool Equals(object obj) { if (obj == null || !(obj is Entity)) return false; if (Object.ReferenceEquals(this, obj)) return true; if (this.GetType() != obj.GetType()) return false; Entity item = (Entity)obj; if (item.IsTransient() || this.IsTransient()) return false; else return item.Id == this.Id; } public override int GetHashCode() { if (!IsTransient()) { if (!_requestedHashCode.HasValue) _requestedHashCode = this.Id.GetHashCode() ^ 31; return _requestedHashCode.Value; } else return base.GetHashCode(); } public static bool operator ==(Entity left, Entity right) { if (Object.Equals(left, null)) return (Object.Equals(right, null)) ? true : false; else return left.Equals(right); } public static bool operator !=(Entity left, Entity right) { return !(left == right); } }
如:添加用户的时候添加一个默认角色相关的表处理
public class TbUser : Entity, IAggregateRoot { public string UserName { get; set; } public string UserPasswrod { get; set; } public string UserPhone { get; set; } public string XXXXX { get; set; } [NotMapped] public List<TbUserRole> TbUserRoles { get; set; } public TbUser() { TbUserRoles = new List<TbUserRole>(); AddDomainEvent(new UserCreatedEvent() { tbUser = this }); } #region 领域职责 结合领域事件处理 黎又铭 /* 如:添加用户的时候添加默认角色 其实本身是可以直接在业务逻辑中写的 有点类是SQL触发器,添加用户的时候构建件默认角色信息模型触发事件添加角色信息 这里有注意到 实体模型并没有强制处理表接口的主外键关系 只是做了模型对象映射 */ /// <summary> /// 添加用户职责 只构建职责 不处理 处理交友领取事件的Command CommandHandler处理 /// </summary> public void AddDefalutRole(TbUserRole tbUserRole) { TbUserRoles.Add(tbUserRole); //添加默认角色的领域事件 AddDomainEvent(new UserRoleCreatedEvent() { TbUserRole = tbUserRole }); } #endregion }
先定义一个创建用户的命令操作: 这里的TbUser是领域时间模型,传递数据以及对领域模型事件操作
public class UserCreateCommand : IRequest<TbUser> { public TbUser tbUser{ get; set; } }
public class UserCreateCommandHandler : IRequestHandler<UserCreateCommand, TbUser> { private IUserRepository _userRepository; public UserCreateCommandHandler(IUserRepository userRepository) { _userRepository = userRepository; } public async Task<TbUser> Handle(UserCreateCommand request, CancellationToken cancellationToken) { await _userRepository.AddUserAsync(request.tbUser); await _userRepository.UnitOfWork.SaveEntitiesAsync(); return request.tbUser; } }
这里还需要一个MediatR的扩展,发布领域事件
static class MediatorExtension { /// <summary> /// 异步处理领域事件 /// </summary> /// <param name="mediator"></param> /// <param name="ctx"></param> /// <returns></returns> public static async Task DispatchDomainEventsAsync(this IMediator mediator, UserDbContext ctx) { var domainEntities = ctx.ChangeTracker .Entries<Entity>() .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()); var tasks = domainEvents .Select(async (domainEvent) => { await mediator.Publish(domainEvent); }); await Task.WhenAll(tasks); } }
下面是订阅领域事件
public class UserRoleNotification : INotificationHandler<UserRoleCreatedEvent> { private IUserRepository _userRepository; public UserRoleNotification(IUserRepository userRepository) { _userRepository = userRepository; } public async Task Handle(UserRoleCreatedEvent notification, CancellationToken cancellationToken) { await _userRepository.AddUserRoleAsync(notification.TbUserRole); }
在controller中的使用:
[HttpPost] [Route("adduser")] public async Task<IActionResult> AddUser([FromBody] TbUser tbUser) { tbUser.AddDefalutRole(new TbUserRole { RoleId = 1, UserId = 1 }); var command = new UserCreateCommand() { tbUser = tbUser }; var result = await _mediator.Send(command); return Ok(result); }
看下效果
如果您觉得阅读本文对您有帮助,请点一下“推荐”按钮,您的“推荐”将是我最大的写作动力!
本文版权归作者和博客园共有,来源网址:http://www.cnblogs.com/liyouming欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接。