MediatR专题--之一 简单了解及使用

本文介绍了MediatR在.NET项目中的应用,包括Request/Response单播消息和Notification广播消息。通过命令模式降低了控制器与业务逻辑的耦合,展示了如何创建命令对象、命令处理程序以及使用MediatR发送命令。同时,还阐述了Notification的多播消息处理,用于处理如用户注册等需要执行多个操作的场景。通过MediatR,可以实现更灵活和解耦的代码结构。
摘要由CSDN通过智能技术生成

项目中使用了MediatR,这里研究一下,这篇文章是这个专题的第一篇,后续会进行源码分析,这篇先介绍和基本使用。

MediatR 有两种方式的消息发送方式:

  • Request / Response (单播消息),指派到 一个 处理程序
  • Notification (广播消息),指派到 多个处理程序

我们先看单播消息
单播消息传递主要涉及 IRequest(消息类型) 和 IRequestHandler(消息处理) 两个接口。
使用 MediatR 的 单播消息 的原因就是用命令模式的原因
下面的链接是讲命令模式的
http://c.biancheng.net/view/1380.html
在程序中,“方法的调用者”与“方法的实现者”之间经常存在紧密的耦合关系,这不利于软件功能的扩展与维护。
比如 我自己写的一个例子
接口:

    public interface IPeopleService
    {
        Task<bool> AddPeople();
        Task<List<object>> GetPeople();
    }

接口实现:

    public class PeopleService : IPeopleService
    {
        public Task<bool> AddPeople()
        {
            Thread.Sleep(2000);
            return Task.FromResult(true);
        }
    }

控制器:

    [Route("api/[controller]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        private readonly IPeopleService peopleService;
        public PersonController(IPeopleService peopleService)
        {
            this.peopleService = peopleService;
        }

        [HttpPost, Route("AddPeople")]
        public async Task<bool> AddPeople()
        {
            return await peopleService.AddPeople();
        }
    }

从上面的代码可以看到,调用方法时,控制器和IPeopleService紧耦合了
下面使用MediatR进行改进
先来看下命令模式的定义:将一个请求封装为一个对象,使发出请求的责任和执行请求的责任分割开。这样两者之间通过命令对象进行沟通。减小了耦合

首先 安装 MediatR.Extensions.Microsoft.DependencyInjection 包
在这里插入图片描述
然后添加

// 扫描 Startup 所在程序集内实现了 Handler 的对象并添加到 IoC 容器中
services.AddMediatR(typeof(Startup));

  1. 创建一个命令对象
    public class PeopleAddComm : IRequest<bool> //bool是该命令处理后的返回结果的类型
    {
    }
  1. 创建命令的实现
    //bool是返回结果的类型
    public class PeopleAddCommHandler : IRequestHandler<PeopleAddComm, bool>
    {
        public Task<bool> Handle(PeopleAddComm request, CancellationToken cancellationToken)
        {
            Thread.Sleep(200);
            return Task.FromResult(true);
        }
    }
  1. 在控制器中使用
    [Route("api/[controller]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        private readonly IMediator _mediator;
        public PersonController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpPost, Route("AddPeople")]
        public async Task<bool> AddPeople()
        {
            PeopleAddComm addComm = new PeopleAddComm();
            return await _mediator.Send(addComm);
        }
    }

和之前的对比,有没有发现 控制器里没有再引入IPeopleService对象了,控制器类和它所调用的方法进行了解耦。


下面来说一下MediatR 的 Notification
多播消息传递涉及 INotification 和 INotificationHandler两个接口,另外多播消息传递是无返回值的。
现在,模拟一个业务场景,用户注册时,要进行以下步骤

  1. 保存到数据库
  2. 记录日志
  3. 发送邮件
    public class RegisterNotification : INotification
    {
        public string LoginName { get; set; }
        public string Pwd { get; set; }
    }
    public class RegisterNotiDbHandler : INotificationHandler<RegisterNotification>
    {
        public Task Handle(RegisterNotification notification, CancellationToken cancellationToken)
        {
            //存入数据库
            Console.WriteLine($"存入数据库 {notification.LoginName}, {notification.Pwd}");
            Thread.Sleep(1000);
            return Task.CompletedTask;
        }

    }
        public Task Handle(RegisterNotification notification, CancellationToken cancellationToken)
        {
            //记录日志
            Console.WriteLine($"记录日志=> {notification.LoginName}, {notification.Pwd}");
            Thread.Sleep(1000);
            return Task.CompletedTask;
        }
    public class RegisterNotiEmailHandler : INotificationHandler<RegisterNotification>
    {
        public Task Handle(RegisterNotification notification, CancellationToken cancellationToken)
        {
            //发送邮件
            Console.WriteLine($"发送邮件=> {notification.LoginName}, {notification.Pwd}");
            Thread.Sleep(1000);
            return Task.CompletedTask;
        }
    }

控制器的方法:

    [Route("api/[controller]")]
    [ApiController]
    public class PersonController : ControllerBase
    {
        private readonly IMediator _mediator;
        public PersonController(IMediator mediator)
        {
            _mediator = mediator;
        }

        [HttpPost, Route("Register")]
        public void Register(string loginName, string pwd)
        {
            RegisterNotification registerNotification = new RegisterNotification { LoginName = loginName, Pwd = pwd };
            _mediator.Publish(registerNotification);
        }
    }

调用结果:
在这里插入图片描述
方法调用顺序:
在这里插入图片描述
经测试是按照类的先后顺序来的


MediatR 中的核心接口主要是 IRequest&IRequestHandler 、INotification&INotificationHandler、IMediator 。
以上就是MediatR的使用,就是这么简单,没有什么复杂的用法,顺便说一下 写MediatR的人也是Automapper的作者。下一篇我们一起看下源码。
源码地址:

https://github.com/jbogard/MediatR

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值