欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Asp.Net Core 使用 MediatR

程序员文章站 2023-02-07 13:30:19
Asp.Net Core 使用 MediatR 项目中使用了CQRS读写分离, 增删改 的地方使用了 ,将进程内消息的发送和处理进行解耦。于是便有了这篇文章,整理并记录一下自己的学习。 遇到问题,解决问题,记录问题,成长就是一步一步走出来的。 是什么? 是的,不管你怎么翻译都查不到该词,好多人都猜测 ......

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

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