Asp.Net Core 使用 MediatR


Asp.Net Core 使用 MediatR

項目中使用了CQRS讀寫分離,增刪改 的地方使用了 MediatR ,將進程內消息的發送和處理進行解耦。於是便有了這篇文章,整理並記錄一下自己的學習。遇到問題,解決問題,記錄問題,成長就是一步一步走出來的。

MediatR 是什么?

是的,不管你怎么翻譯都查不到該詞,好多人都猜測說是作者將Mediator筆誤寫成MediatR了,哈哈哈,該問題暫且不論。

作者說這是一個野心很小的庫,試圖解決一個問題———解耦進程內消息的發送與處理。

一、下載Nuget包

Asp.Net Core 我們可以使用擴展了 Microsoft.Extensions.DependencyInjectionMediatR 的擴展包 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 端都是異步的,只要你的工作是可以等待的,你的處理器就可以使用Asyncawait關鍵字

不為寫博客而寫博客。記錄,一方面梳理和整理自己的所學和思路,另一方面在以后遇到同樣問題時,而不必再花費不必要的時間。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM