zoukankan      html  css  js  c++  java
  • 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关键字

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

  • 相关阅读:
    小学四则算式扩充
    软件工程初涉之感
    回头
    个人最终总结
    团队作业
    结对编程
    老李的blog使用日记(3)
    进度
    老李的blog使用日记(2)
    红果果
  • 原文地址:https://www.cnblogs.com/imlxp/p/11248704.html
Copyright © 2011-2022 走看看