Asp.Net Core 使用 MediatR

2022-10-18,,,

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关键字

不为写博客而写博客。记录,一方面梳理和整理自己的所学和思路,另一方面在以后遇到同样问题时,而不必再花费不必要的时间。

《Asp.Net Core 使用 MediatR.doc》

下载本文的Word格式文档,以方便收藏与打印。