MediatR使用

Posted wudequn

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MediatR使用相关的知识,希望对你有一定的参考价值。

什么是MediatR

项目地址:https://github.com/jbogard/MediatR

Simple mediator implementation in .NET
In-process messaging with no dependencies.
Supports request/response, commands, queries, notifications and events, synchronous and async with intelligent dispatching via C# generic variance.

.NET中的简单中介者模式实现,一种进程内消息传递机制(无其他外部依赖)。 支持以同步或异步的形式进行请求/响应,命令,查询,通知和事件的消息传递,并通过C#泛型支持消息的智能调度。

 

什么是中介者模式

定义:

定义一个中介对象来封装一系列对象之间的交互,使原有对象之间的耦合松散,且可以独立地改变它们之间的交互。中介者模式又叫调停模式,它是迪米特法则的典型应用。

技术图片

 

中介者模式是一种对象行为型模式,其主要优点如下。
降低了对象之间的耦合性,使得对象易于独立地被复用。
将对象间的一对多关联转变为一对一的关联,提高系统的灵活性,使得系统易于维护和扩展。

其主要缺点是:当同事类太多时,中介者的职责将很大,它会变得复杂而庞大,以至于系统难以维护。

 

技术图片

抽象中介者(Mediator)角色:它是中介者的接口,提供了同事对象注册与转发同事对象信息的抽象方法。

具体中介者(ConcreteMediator)角色:实现中介者接口,定义一个 List 来管理同事对象,协调各个同事角色之间的交互关系,因此它依赖于同事角色。

抽象同事类(Colleague)角色:定义同事类的接口,保存中介者对象,提供同事对象交互的抽象方法,实现所有相互影响的同事类的公共功能。

具体同事类(Concrete Colleague)角色:是抽象同事类的实现者,当需要与其他同事对象交互时,由中介者对象负责后续的交互。

 

应用场景:

对于关系比较复杂的网状结构,改成点状结构,降低之间的耦合。

比如说:

1、每一个都认识很多朋友,大家需要记住各自朋友的联系方式,大家可以用过微信联系。那么微信就是一个中介者.

2、MVC框架中  控制器(C)  就是模型(M)和视图(V)的中介者

3、房地产平台  与  买房者  卖房者

MediatR使用

MediatR作用

1、事件/消息驱,发布/订阅型的业务逻辑。

2、解耦网状关系

3、将命令的构造和命令的处理分开

4、CQRS

MediatR核心对象

1、IMediator

//终结者对象

 

2、IRequest  IRequest<T>

请求模型。请求响应模式使用。

3、IRequestHandler<in TRequest,out TResponse>

处理请求IRequest<T>,的处理者。

如果有多个处理IRequestHandler会用最后一个

 

4、services.AddMediatR(程序集)

扫描程序集,将相关的类注入进去

 

5、INotification

通知模型

6、INotificationHandler<in TNotification>

通知处理者

 

上面2、3用于请求响应模式(一对一)。5、6用于通知发布模型(一对多)

 

MediatR消息类型

1、Request/Response   请求响应模式

请求/响应模式,也可以叫做命令模式,主要适用于命令和查询场景。一个请求只能被一个处理者捕获,如果存在多个处理者,那么只有最后一个处理者会被激活。

单播消息传输,也就是一对一的消息传递,一个消息对应一个消息处理。其通过IRequest来抽象单播消息,用IRequestHandler进行消息处理。

模型定义

IRequest<string>里面string 返回参数。也支持不返回参数的GetOrderByIdRequestModel : IRequest
    /// <summary>
    /// 请求/响应接口适用于命令和查询场景。 *都只能有一个Handler,如果注册多个,只有最后一个会生效。
    /// </summary>
    public class GetOrderByIdRequestModel : IRequest<string>
    {
        public string OrderId { get; set; }
    }

处理者定义

IRequestHandler<GetOrderByIdRequestModel, string>   第一个参数请求参数,第二个返回参数。
    public class GetOrderByIdQueryHandler : IRequestHandler<GetOrderByIdRequestModel, string>
    {
        public Task<string> Handle(GetOrderByIdRequestModel request, CancellationToken cancellationToken)
        {
            //do something
            return Task.FromResult(request.OrderId);
        }
    }

调用

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

        [HttpPost]
        public async Task<IActionResult> Post([FromBody]CreateOrderRequestModel requestModel)
        {
            var response = await _mediator.Send(requestModel);
            return Ok(response);
        }

        [HttpGet]
        public async Task<IActionResult> Get([FromQuery]GetOrderByIdRequestModel requestModel)
        {
            var response = await _mediator.Send(requestModel);
            return Ok(response);
        }
    }

 控制器里这么玩,控制器关注于身份认证、基础设施、缓存等一些非业务逻辑处理,不在关心业务

2、Notification  发布模式

我使用它的大多数情况是Notification这种模式。因为我希望用它来做模型的领域事件。

发布模式,一般用于发布一个事件,通知订阅者某件事情已经发生,对此事感兴趣的订阅者可以采取行动了。一般是一个发布者,多个订阅者。(可以改造成发布到队列)

多播消息传输,也就是一对多的消息传递,一个消息对应多个消息处理。其通过INotification来抽象多播消息,对应的消息处理类型为INotificationHandler。

模型

    /// <summary>
    /// 发布消息的模型
    /// </summary>
    public class OrderCreatedEvent : INotification
    {
        public string UserId { get; set; }

        public OrderCreatedEvent(string orderId)
        {
            this.UserId = orderId;
        }
    }

处理者

    /// <summary>
    /// 领域事件处理者
    /// 一个事件可以有多个处理者
    /// </summary>
    public class OrderCreatedDomainEventHandler : INotificationHandler<OrderCreatedEvent>
    {
        private readonly ILogger _logger;

        public OrderCreatedDomainEventHandler(ILogger<OrderCreatedDomainEventHandler> logger)
        {
            _logger = logger;
        }

        public Task Handle(OrderCreatedEvent notification, CancellationToken cancellationToken)
        {
            _logger.LogInformation($"Order has found by userid id: {notification.UserId} from publisher");
            return Task.CompletedTask;
        }
    }

发布消息

            //do something...
            await _mediator.Publish(new OrderCreatedEvent(request.UserId), cancellationToken);
            return request.UserId;

这种模式可以用于 发送领域事件 

 

 

代码下载

 

以上是关于MediatR使用的主要内容,如果未能解决你的问题,请参考以下文章

MediatR 在 IIS 上找不到处理程序

来自管道行为的 MediatR 流畅的验证响应

如何使用FluentAssertions在XUnit中测试MediatR处理程序

导航到 Visual Studio 2019(或 Rider)中的 MediatR 处理程序

MediatR 发布和 MediatR 发送

使用 MediatR 链接处理程序