ASP.NET Core MVC 入门到精通 - 使用MediatR

1. MediatR

MediatR .NET中的简单中介者模式实现,一种进程内消息传递机制(无其他外部依赖)。支持以同步或异步的形式进行请求/响应,命令,查询,通知和事件的消息传递,并通过C#泛型支持消息的智能调度。
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.
另:中介者模式 - 定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

2. 安装 & 配置

对于.NET5 (.net core), 使用nuget 安装MediatR.Extensions.Microsoft.DependencyInjection.
配置:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. services.AddControllersWithViews();
  4. services.AddMediatR(typeof(Startup));
  5. }

3. MediatR消息类型

3.1. Notifications 通知模式

Notifications 通知模式用于生产者发送通知,消费者(可以多个)接收到通知后,进行后续处理。
例:一个APS.NET 页面,访问时,发送Notifications通知;消费者简单记录收到通知的时间。

3.1.1. 定义基于INotification的通知类

  1. public class Ping : INotification { }

3.1.2. 定义消费者(关注通知的处理方法)

  1. public class Pong1 : INotificationHandler<Ping>
  2. {
  3. public Task Handle(Ping notification, CancellationToken cancellationToken)
  4. {
  5. Debug.WriteLine($"Pong1, {DateTime.Now}");
  6. return Task.CompletedTask;
  7. }
  8. }
  9. public class Pong2 : INotificationHandler<Ping>
  10. {
  11. public Task Handle(Ping notification, CancellationToken cancellationToken)
  12. {
  13. Debug.WriteLine($"Pong2, {DateTime.Now}");
  14. return Task.CompletedTask;
  15. }
  16. }

3.1.3. 发送消息通知

  1. // 基于dotnet core的依赖注入,注入IMediator对象
  2. private readonly IMediator _mediator;
  3. public HomeController(ILogger<HomeController> logger, IMediator mediator)
  4. {
  5. _logger = logger;
  6. _mediator = mediator;
  7. }
  8. public async Task<IActionResult> IndexAsync()
  9. {
  10. // e.g. 访问首页时,发送通知
  11. await _mediator.Publish(new Ping());
  12. return View();
  13. }

3.1.4. 输出

  1. Pong1, 5/27/2021 4:37:18 PM
  2. Pong2, 5/27/2021 4:37:18 PM

3.2. Request/Response 请求响应模式

request/response用于命令和查询的场景。

3.2.1. 创建请求类:

  1. public class RequestModel: IRequest<string>
  2. {
  3. }

3.2.2. 创建请求处理类

不同于通知模式,request/response只能有一个请求处理。

  1. public class RequestHandeler : IRequestHandler<RequestModel, string>
  2. {
  3. public Task<string> Handle(RequestModel request, CancellationToken cancellationToken)
  4. {
  5. return Task.FromResult($"Pong {DateTime.Now}"); // 测试,返回内容给request
  6. }
  7. }

3.2.3. 页面中发送请求

  1. private readonly ILogger<HomeController> _logger;
  2. private readonly IMediator _mediator;
  3. public HomeController(ILogger<HomeController> logger, IMediator mediator)
  4. {
  5. _logger = logger;
  6. _mediator = mediator;
  7. }
  8. public async Task<IActionResult> IndexAsync()
  9. {
  10. // send request, and show Response
  11. var response = await _mediator.Send(new RequestModel());
  12. Debug.WriteLine("Got response in controller: " +response);
  13. return View();
  14. }

3.2.4. 输出

  1. Got response in controller: Pong 5/28/2021 2:04:26 PM

4. 总结