MediatR 試用紀錄

一個很受歡迎的套件。常用於實作CQRS pattern。試用看看。

引言

最近經常看到 CQRS pattern,然後使用MediatR實作。 本人對CQRS沒興趣,有興趣的只有MediatR的訊息傳遞模組。

MediatR應用類型現在有三種

  • IRequest (including generic variants and Unit) 就是 Request/Reponse模式。

  • INotification 通知模式,也是本人最有興趣的。

  • IStreamRequest 未試用。

開發前置準備

開發環境

  • IDE: Visual Studio 2022

  • platform: .NET6

  • project type: Blaozr WASM hosted app

安裝套件

PM> Install-Package MediatR
PM> Install-Package MediatR.Extensions.Microsoft.DependencyInjection

註冊

Program.cs
// Add services to the container.
services.AddMediatR(typeof(Program));

關鍵指令紀錄

IRequest 模式

定義 Request/Response 與其 Handler:

using MediatR;
namespace YourProject.MediatRHandler;

/// 此例是CQRS pattern 中的 Query 簡要範例,Command 也是差不多的用法。
/// IRequest Handler
public class QueryUserHandler : IRequestHandler<QueryUserRequest, QueryUserResponse>
{
    public Task<QueryUserResponse> Handle(QueryUserRequest request, CancellationToken cancellationToken)
    {
      return Task.FromResult(new QueryUserResponse { 
        DisplayName = $"我是{request.Id}的名字"      
      });
    }
}

/// Response
public class QueryUserResponse
{
  public string DisplayName { get; set; } = string.Empty;
}

/// Request
public class QueryUserRequest : IRequest<QueryUserResponse>
{
  public int Id { get; set; }
}

應用:

MyDataController.cs
[Route("api/[controller]")]
[ApiController]
public class MyDataController : ControllerBase
{
  readonly MediatR.IMediator _mediator;

  public MyDataController(MediatR.IMediator mediator)
  {
    _mediator = mediator;
  }
  
  [HttpPost("[action]")]
  public QueryUserResponse QryUserData()
  {
    var response = _mediator.Send(new QueryUserRequest { Id = 987 }).Result;
    return response;
  }  
}

INotification模式

定義 Notification:

using MediatR;
namespace YourProject.MediatRHandler;

/// 定義 INotification
public class Ping : INotification {
  public string Msg { get; set; } = string.Empty;
}

定義接收 Notification 的 handler:

using MediatR;
namespace YourProject.MediatRHandler;

/// INotification Handler - 接收Notification
/// ※接收方原則上在那都可以,此為到方便測試所以寫在附近。
public class Pong1 : INotificationHandler<Ping>
{
  public Task Handle(Ping notification, CancellationToken cancellationToken)
  {
    Debug.WriteLine($"Pong1:{notification.Msg}:@{DateTime.Now}");
    return Task.CompletedTask;
  }
}

/// INotification Handler - 另一個接收Notification
/// ※接收方原則上在那都可以,此為到方便測試所以寫在附近。
public class Pong2 : INotificationHandler<Ping>
{
  public Task Handle(Ping notification, CancellationToken cancellationToken)
  {
    Debug.WriteLine($"Pong2:{notification.Msg}:@{DateTime.Now}");
    return Task.CompletedTask;
  }
}

應用:

MyDataController.cs
[Route("api/[controller]")]
[ApiController]
public class MyDataController : ControllerBase
{
  readonly MediatR.IMediator _mediator;

  public MyDataController(MediatR.IMediator mediator)
  {
    _mediator = mediator;
  }
  
  [HttpPost("[action]")]
  public QueryUserResponse QryUserData()
  {
    // 比如:執行商業邏輯
    var response = _mediator.Send(new QueryUserRequest { Id = 987 }).Result;
    
    // 比如:當完成商業邏輯後送出通知訊息。
    // 送出 Notification
    _mediator.Publish(new MediatRHandler.Ping { Msg = "XY23" });
    
    return response;
  }  
}

試用心得

CQRS pattern with MediatR 的應用應該比較適合實作微服務。比如:非同步的、資料後送類的、通知類的、可射後不理的,比如像是 Action Log 或資料歸檔 Data Archive 或 Authz 這類domain範圍不大的、數據相依性不多甚至沒有的等等簡單就能封裝的(closure)資料包的應用。

  • 其他說明:可以實作Notification、CQRS Pattern。很受觀迎的CQRS實作技術。

  • 試用心得優點:適合用於後端,如與WebApi搭配使用。

  • 試用心得缺點:可惜其Notification Publisn 在 WebAssembly 前端無效。

Last updated