MediatR源码详解(就差手摸手了)
文章目录
一、项目介绍
MediatR是.NET中一种简单的实现进程内的消息传递机制的类库。支持同步或者异步的形式进行请求响应,命令,查询。通知和事件的传递
github地址:https://github.com/jbogard/MediatR
作者:jbogard
二、源码分析
2.1、消息传递之单点传递:
所谓的单点传递,就是在消息传递中,存在一个发消息的,还存在一个接收消息的,就像生活中,我们聊QQ/微信就属于消息传递,而我们现在要聊的就是消息传递中的单点传递也就是私聊,一对一的进行传递。
2.1.1 IRequest 接口:
/// <summary>
/// Marker interface to represent a request with a void response
/// </summary>
public interface IRequest : IRequest<Unit> {
}
/// <summary>
/// Marker interface to represent a request with a response
/// </summary>
/// <typeparam name="TResponse">Response type</typeparam>
public interface IRequest<out TResponse> : IBaseRequest {
}
/// <summary>
/// Allows for generic type constraints of objects implementing IRequest or IRequest{TResponse}
/// </summary>
public interface IBaseRequest {
}
IRequest相关接口,在消息传递中,是用于一对一的消息传递参数请求所定义相关参数规范的接口,可以理解为定义消息传递的参数格式所需要的接口 我们可以看到,这里有三个相关接口,最底层的是IBaseRequest接口,然后是一个IRequest<TRequest>接口,最后是IRequest接口,首先讲一下三个接口,IBaseRequest接口,其实就是最基础的接口,起到了一个类型约束的作用,所有的参数类型,都必须继承自IBaseRequst接口,而IRequestt<TRequest>接口呢,则是定义了在消息传递的逻辑处理中,所需要返回的返回值的类型,这样就起到了,消息的传递以及响应的作用,发出消息也定义了这个消息所需要的响应是什么。最后一个IRequest接口,继承于IRequest<Unit>接口,这是什么意思呢,这就很厉害了,它是用Unit结构,来当作返回类型,从而实现了无返回值的消息参数类型。
2.1.2 IRequestHandler接口:
/// <summary>
/// Defines a handler for a request
/// </summary>
/// <typeparam name="TRequest">The type of request being handled</typeparam>
/// <typeparam name="TResponse">The type of response from the handler</typeparam>
public interface IRequestHandler<in TRequest, TResponse> where TRequest : IRequest<TResponse>
{
/// <summary>
/// Handles a request
/// </summary>
/// <param name="request">The request</param>
/// <param name="cancellationToken">Cancellation token</param>
/// <returns>Response from the request</returns>
Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken);
}
/// <summary>
/// Defines a handler for a request with a void (<see cref="Unit" />) response.
/// You do not need to register this interface explicitly with a container as it inherits from the base <see cref="IRequestHandler{TRequest, TResponse}" /> interface.
/// </summary>
/// <typeparam name="TRequest">The type of request being handled</typeparam>
public interface IRequestHandler<in TRequest> : IRequestHandler<TRequest, Unit> where TRequest : IRequest<Unit>
{
}
/// <summary>
/// Wrapper class for a handler that asynchronously handles a request and does not return a response
/// </summary>
/// <typeparam name="TRequest">The type of request being handled</typeparam>
public abstract class AsyncRequestHandler<TRequest> : IRequestHandler<TRequest> where TRequest : IRequest
{
async Task<Unit> IRequestHandler<TRequest, Unit>.Handle(TRequest request, CancellationToken cancellationToken)
{
await Handle(request, cancellationToken).ConfigureAwait(false);
return Unit.Value;
}
/// <summary>
/// Override in a derived class for the handler logic
/// </summary>
/// <param name="request">Request</param>
/// <param name="cancellationToken"></param>
/// <returns>Response</returns>
protected abstract Task Handle(TRequest request, CancellationToken cancellationToken);
}
/// <summary>
/// Wrapper class for a handler that synchronously handles a request and returns a response
/// </summary>
/// <typeparam name="TRequest">The type of request being handled</typeparam>
/// <typeparam name="TResponse">The type of response from the handler</typeparam>
public abstract class RequestHandler<TRequest, TResponse> : IRequestHandler<TRequest, TResponse> where TRequest : IRequest<TResponse>
{
Task<TResponse> IRequestHandler<TRequest, TResponse>.Handle(TRequest request, CancellationToken cancellationToken)
=> Task.FromResult(Handle(request));
/// <summary>
/// Override in a derived class for the handler logic
/// </summary>
/// <param name="request">Request</param>
/// <returns>Response</returns>
protected abstract TResponse Handle(TRequest request);
}
/// <summary>
/// Wrapper class for a handler that synchronously handles a request does not return a response
/// </summary>
/// <typeparam name="TRequest">The type of request being handled</typeparam>
public abstract class RequestHandler<TRequest> : IRequestHandler<TRequest> where TRequest : IRequest
{
Task<Unit> IRequestHandler<TRequest, Unit>.Handle(TRequest request, CancellationToken cancellationToken)
{
Handle(request);
return Unit.Task;
}
protected abstract void Handle(TRequest request);
}
既然说到了微信聊天,我们肯定知道聊天最起码得是俩人的事,特别是私聊,对面必须的有一个消息接收者,没有接收者我们发出去的就不是消息,而是寂寞。而IRequestHandler接口的主要作用是接收消息参数进行响应的逻辑处理,在这个接口下面,还有三个抽象类,采用的是包装器模式,对这个接口进行额外的功能实现,
可以看出,这三个抽象类实现了有响应,无响应这两种情况的同步以及异步不同模式下的处理方式(就像Boss直聘里面经常出现的:消息未读、已读不回、还有已读明天回),而方法中的抽象方法更是为了在不同情况下,所继承的实现类根据具体业务来实现具体逻辑使用。
2.2、消息传递之消息通知
通知,这个就有趣了,通知可以是单独通知一个人,也可以通知一群人,在经历2020年初疫情之后,大家肯定对网上很火某地村长拿大喇叭喊话通知这段视频记忆犹新吧,从这里我们就可以看出消息的通知,可以是针对一到N个人进行通知的,而且通知后不需要每个人进行回复响应,想要接收到通知以后有条不紊的做就完了。所以接下来说的就是项目中通知的实现。
/// <summary>
/// Marker interface to represent a notification
/// </summary>
public interface INotification {
}
/// <summary>
/// Defines a handler for a notification
/// </summary>
/// <typeparam name="TNotification">The type of notification being handled</typeparam>
public interface INotificationHandler<in TNotification> where TNotification : INotification
{
/// <summary>
/// Handles a notification
/// </summary>
/// <param name="notification">The notification</param>
/// <param name="cancellationToken">Cancellation token</param>
Task Handle(TNotification notification, Can