Asp.Net Core 使用 MediatR

摘要:
DotnetaddpackageMediator。扩展。Microsoft.DependencyInjection II。注册服务v7.0.0版本服务。AddMediator(类型(MyHandler));或服务。AddMediator(类型(启动)。GetTypeInfo()。组装);设置
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第1张

免责声明:文章转载自《Asp.Net Core 使用 MediatR》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇各种媒体数据以 base64 编码方式直接嵌入网页中的写法c#原理:c#代码是怎么运行的、实例化时发生了什么、静态对象(类、方法、变量、属性)的原理下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

矩阵求逆c++实现

矩阵求逆c++实现 http://www.2cto.com/kf/201405/297388.html 2014-05-02     我来说两句    来源:矩阵求逆c++实现   收藏    我要投稿 高斯消元法可以用来找出一个可逆矩阵的逆矩阵。设A 为一个N * N的矩阵,其逆矩阵可被两个分块矩阵表示出来。将一个N * N单位矩阵 放在...

HTML邮件模板

邮件要求兼容 outlook 等邮箱软件,发现很多样式都不生效。找到的模板如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html x...

一个漂亮的输出MySql数据库表结构的PHP页面

经常为了方便和直观,我们会首先直接在数据库中设计出表,但是接下来又要将表的结构和设计编写在设计文档中,以便编码的时候可以直观的查询,一旦数据库表非常多,字段非常多的时候,这无疑是件非常郁闷的工作。 这是一个漂亮的PHP页面,可以自动输出MySql数据库所有表结构,大大方便了文档的编写工作,也同时非常方便编码的时候进行查询。当然在设计MySql数据库表和字段...

mybaits3.2.8 别名包扫描通配符

<mybatis.version>3.2.8</mybatis.version><mybatis.spring.version>1.2.2</mybatis.spring.version><mybatis.generator.version>1.3.2</mybatis.generator....

php 命名空间(要求php5.3以上)

要求php5.3以上 <?phpnamespace test;// 命名空间与目录类似功能,也可定义子命名空间,用分层的方式定义:/*namespace mydirokproject; 在声明命名空间之前唯一合法的代码是用于定义源文件编码方式的 declare 语句。另外,所有非 PHP 代码包括空白符都不能出现在命名空间的声明之前: */const...

vue之provide和inject

官方说: 当我们需要从父组件向子组件传递数据时,我们使用 props。想象一下这样的结构:有一些深度嵌套的组件,而深层的子组件只需要父组件的部分内容。在这种情况下,如果仍然将 prop 沿着组件链逐级传递下去 个人理解: 在祖先组件中定义provide(提供)给后代组件的数据或方法,在后代组件中可以通过inject(接受)提供的数据或方法 举个栗子, 想做...