什么是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;
這種模式可以用於 發送領域事件