Asp.Net Core 使用 MediatR 項目中使用了CQRS讀寫分離, 增刪改 的地方使用了 ,將進程內消息的發送和處理進行解耦。於是便有了這篇文章,整理並記錄一下自己的學習。 遇到問題,解決問題,記錄問題,成長就是一步一步走出來的。 是什麼? 是的,不管你怎麼翻譯都查不到該詞,好多人都猜測 ...
Asp.Net Core 使用 MediatR
項目中使用了CQRS讀寫分離,增刪改 的地方使用了
MediatR
,將進程內消息的發送和處理進行解耦。於是便有了這篇文章,整理並記錄一下自己的學習。遇到問題,解決問題,記錄問題,成長就是一步一步走出來的。
MediatR
是什麼?
是的,不管你怎麼翻譯都查不到該詞,好多人都猜測說是作者將Mediator筆誤寫成MediatR了,哈哈哈,該問題暫且不論。
作者說這是一個野心很小的庫,試圖解決一個問題———解耦進程內消息的發送與處理。
一、下載Nuget包
Asp.Net Core 我們可以使用擴展了 Microsoft.Extensions.DependencyInjection
的 MediatR
的擴展包 MediatR.Extensions.Microsoft.DependencyInjection
,方便直接註冊服務。
安裝該Nuget包,會自動安裝MediatR
。寫文檔時使用的版本:v7.0.0
Package Manager : Install-Package MediatR.Extensions.Microsoft.DependencyInjection
或
CLI : dotnet add package MediatR.Extensions.Microsoft.DependencyInjection
二、註冊服務
v7.0.0版本
services.AddMediatR(typeof(MyHandler));
或
services.AddMediatR(typeof(Startup).GetTypeInfo().Assembly);
//這裡用的Startup,其實Hanler所在的項目中的任何一個文件都可
如果使用的是 v6.0.1
版本時 只需要 services.AddMediatR()
即可。
三、基本使用
MediatR
有兩種方式的消息發送方式:
Request
/Response
(請求/響應消息),指派到 一個 處理程式Notification
(廣播消息),指派到 多個 處理程式
請求和響應(消息單播)
也就是一個消息對應一個消息處理。
請求和響應介面處理命令和查詢場景,首先,創建一個消息:
public class CreateUserCommand : IRequest<string>
{
public string Name { get; set; }
}
然後創建一個處理器:
public class CreateUserHandler : IRequestHandler<CreateUserCommand, string>
{
public async Task<string> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
return await Task.FromResult($"New name is {request.Name}");
}
}
最後,通過 mediator 發送消息:
[HttpPost("User")]
public async Task<string> CreateUserAsync([FromQuery] string name)
{
var response = await _mediator.Send(new CreateUserCommand { Name = name});
return response;
}
如果你的消息不需要返迴響應消息,可以使用 AsyncRequestHandler<TRequest>
基礎類:
//消息
public class NoResponseCommand : IRequest { }
//處理器
public class NoResponseHandler : AsyncRequestHandler<NoResponseCommand>
{
protected override async Task Handle(NoResponseCommand request, CancellationToken cancellationToken)
{
//handle the logic
}
}
//介面
[HttpPost("NoResponse")]
public async Task NoResponseAsync()
{
await _mediator.Send(new NoResponseCommand());
}
請求類型
在 MediatR
中有兩種請求類型。一種有返回值,一種沒有返回值。
IRequest<T>
:該請求會返回一個值IRequest
:該請求沒有返回值
為了簡化執行管道,IRequest
繼承了IRequest<Unit>
介面,其中 Unit
代表了一個終端或可忽略的返回類型。
每個請求類型都有屬於自己對應的處理器介面:
IRequestHandler<T,U>
:實現它,並返回Task<U>
.RequestHandler<T,U>
:繼承它,並返回Task<U>
.
然後是對於那些沒有返回值的請求的處理器介面:
IRequestHandler<T>
:實現它,並返回Task<Unit>
.AsyncRequestHandler<T>
:繼承它,並返回Task
.RequestHandler<T>
:繼承它,什麼也不用返回 (void
)
發佈(消息多播)
也就是發佈一個消息,會有多個消息處理器進行消息處理。
對於廣播,首先要創建你的廣播消息:
public class MyNotificationCommand: INotification
{
/// <summary>
/// 廣播的內容
/// </summary>
public string Message { get; set; }
}
接下來創建0個或多個處理器來處理廣播:
public class FirstMyNotificationHandler : INotificationHandler<MyNotificationCommand>
{
public async Task Handle(MyNotificationCommand notification, CancellationToken cancellationToken)
{
//針對廣播的內容做進一步處理
Debug.WriteLineIf(!string.IsNullOrEmpty(notification.Message), $"First notification handler:{notification.Message}");
}
}
public class SecondMyNotificationHandler : INotificationHandler<MyNotificationCommand>
{
public async Task Handle(MyNotificationCommand notification, CancellationToken cancellationToken)
{
//針對廣播的內容做進一步處理
Debug.WriteLineIf(!string.IsNullOrEmpty(notification.Message), $"Second notification handler:{notification.Message}");
}
}
最後通過 mediator 發佈消息。
[HttpPost("Publish")]
public async Task PublishNotificationAsync([FromQuery] string name)
{
await _mediator.Publish(new MyNotificationCommand {Message = name });
}
以上代碼會在輸出欄列印 First和Second 兩次的內容。
非同步
Send/Publish在 IMediatR
端都是非同步的,只要你的工作是可以等待的,你的處理器就可以使用Async
或await
關鍵字
不為寫博客而寫博客。記錄,一方面梳理和整理自己的所學和思路,另一方面在以後遇到同樣問題時,而不必再花費不必要的時間。