MediatR使用
Posted wudequn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MediatR使用相关的知识,希望对你有一定的参考价值。
什么是MediatR
项目地址:https://github.com/jbogard/MediatR
Simple mediator implementation in .NET In-process messaging with no dependencies. Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance.
.NET中的简单中介者模式实现,一种进程内消息传递机制(无其他外部依赖)。 支持以同步或异步的形式进行请求/响应,命令,查询,通知和事件的消息传递,并通过C#泛型支持消息的智能调度。
什么是中介者模式
定义:
定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。
中介者模式是一种对象行为型模式,其主要优点如下。
降低了对象之间的耦合性,使得对象易于独立地被复用。
将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。
其主要缺点是:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。
抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。
具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。
抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。
具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。
应用场景:
对于关系比较复杂的网状结构,改成点状结构,降低之间的耦合。
比如说:
1、每一个都认识很多朋友,大家需要记住各自朋友的联系方式,大家可以用过微信联系。那么微信就是一个中介者.
2、MVC框架中 控制器(C) 就是模型(M)和视图(V)的中介者
3、房地产平台 与 买房者 卖房者
MediatR使用
MediatR作用
1、事件/消息驱,发布/订阅型的业务逻辑。
2、解耦网状关系
3、将命令的构造和命令的处理分开
4、CQRS
MediatR核心对象
1、IMediator
//终结者对象
2、IRequest IRequest<T>
请求模型。请求响应模式使用。
3、IRequestHandler<in TRequest,out TResponse>
处理请求IRequest<T>,的处理者。
如果有多个处理IRequestHandler会用最后一个
4、services.AddMediatR(程序集)
扫描程序集,将相关的类注入进去
5、INotification
通知模型
6、INotificationHandler<in TNotification>
通知处理者
上面2、3用于请求响应模式(一对一)。5、6用于通知发布模型(一对多)
MediatR消息类型
1、Request/Response 请求响应模式
请求/响应模式,也可以叫做命令模式,主要适用于命令和查询场景。一个请求只能被一个处理者捕获,如果存在多个处理者,那么只有最后一个处理者会被激活。
单播消息传输,也就是一对一的消息传递,一个消息对应一个消息处理。其通过IRequest来抽象单播消息,用IRequestHandler进行消息处理。
模型定义
IRequest<string>里面string 返回参数。也支持不返回参数的GetOrderByIdRequestModel : IRequest
/// <summary> /// 请求/响应接口适用于命令和查询场景。 *都只能有一个Handler,如果注册多个,只有最后一个会生效。 /// </summary> public class GetOrderByIdRequestModel : IRequest<string> { public string OrderId { get; set; } }
处理者定义
IRequestHandler<GetOrderByIdRequestModel, string> 第一个参数请求参数,第二个返回参数。
public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdRequestModel, string> { public Task<string> Handle(GetOrderByIdRequestModel request, CancellationToken cancellationToken) { //do something return Task.FromResult(request.OrderId); } }
调用
[Route("api/[controller]")] [ApiController] public class MediatRDemonController : ControllerBase { private readonly IMediator _mediator; public MediatRDemonController(IMediator mediator) { _mediator = mediator; } [HttpPost] public async Task<IActionResult> Post([FromBody]CreateOrderRequestModel requestModel) { var response = await _mediator.Send(requestModel); return Ok(response); } [HttpGet] public async Task<IActionResult> Get([FromQuery]GetOrderByIdRequestModel requestModel) { var response = await _mediator.Send(requestModel); return Ok(response); } }
控制器里这么玩,控制器关注于身份认证、基础设施、缓存等一些非业务逻辑处理,不在关心业务
2、Notification 发布模式
我使用它的大多数情况是Notification这种模式。因为我希望用它来做模型的领域事件。
发布模式,一般用于发布一个事件,通知订阅者某件事情已经发生,对此事感兴趣的订阅者可以采取行动了。一般是一个发布者,多个订阅者。(可以改造成发布到队列)
多播消息传输,也就是一对多的消息传递,一个消息对应多个消息处理。其通过INotification来抽象多播消息,对应的消息处理类型为INotificationHandler。
模型
/// <summary> /// 发布消息的模型 /// </summary> public class OrderCreatedEvent : INotification { public string UserId { get; set; } public OrderCreatedEvent(string orderId) { this.UserId = orderId; } }
处理者
/// <summary> /// 领域事件处理者 /// 一个事件可以有多个处理者 /// </summary> public class OrderCreatedDomainEventHandler : INotificationHandler<OrderCreatedEvent> { private readonly ILogger _logger; public OrderCreatedDomainEventHandler(ILogger<OrderCreatedDomainEventHandler> logger) { _logger = logger; } public Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken) { _logger.LogInformation($"Order has found by userid id: {notification.UserId} from publisher"); return Task.CompletedTask; } }
发布消息
//do something... await _mediator.Publish(new OrderCreatedEvent(request.UserId), cancellationToken); return request.UserId;
这种模式可以用于 发送领域事件
以上是关于MediatR使用的主要内容,如果未能解决你的问题,请参考以下文章
如何使用FluentAssertions在XUnit中测试MediatR处理程序