Asp.Net Core 使用 MediatR

Asp.Net Core 使用 MediatR

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

MediatR 是什麼?

是的,無論你怎麼翻譯都查不到該詞,好多人都猜想說是做者將Mediator筆誤寫成MediatR了,哈哈哈,該問題暫且不論。asp.net

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

1、下載Nuget包

Asp.Net Core 咱們可使用擴展了 Microsoft.Extensions.DependencyInjectionMediatR 的擴展包 MediatR.Extensions.Microsoft.DependencyInjection,方便直接註冊服務。async

安裝該Nuget包,會自動安裝MediatR。寫文檔時使用的版本:v7.0.0ide

Package Manager : Install-Package MediatR.Extensions.Microsoft.DependencyInjection
或
CLI : dotnet add package MediatR.Extensions.Microsoft.DependencyInjection

2、註冊服務

v7.0.0版本學習

services.AddMediatR(typeof(MyHandler));
或
services.AddMediatR(typeof(Startup).GetTypeInfo().Assembly);
//這裏用的Startup,其實Hanler所在的項目中的任何一個文件均可

若是使用的是 v6.0.1 版本時 只須要 services.AddMediatR() 便可。.net

3、基本使用

MediatR 有兩種方式的消息發送方式:翻譯

  • Request/Response (請求/響應消息),指派到 一個 處理程序
  • Notification (廣播消息),指派到 多個 處理程序

請求和響應(消息單播)

也就是一個消息對應一個消息處理。code

請求和響應接口處理命令和查詢場景,首先,建立一個消息:繼承

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關鍵字

不爲寫博客而寫博客。記錄,一方面梳理和整理本身的所學和思路,另外一方面在之後遇到一樣問題時,而沒必要再花費沒必要要的時間。

相關文章
相關標籤/搜索