博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
一起来学习.net core程序使用中介者模式:MediatR插件
阅读量:5153 次
发布时间:2019-06-13

本文共 7513 字,大约阅读时间需要 25 分钟。

       中介者模式是一种常见的设计模式,旨再降低程序的耦合性,因为传统的三层模式层层之间需要显示的调用,必须上层依赖下层,耦合性很高,为了解耦,将所有的指令单独放在一个位置处理,其他位置均通过这个位置来间接的调用,从而减少耦合,具体的可以参考,建议先了解下DDD里面的事件总线和命令分发。

        实现中介者模式有很多方式,例如就是一种很好用的插件,作者的介绍是这样说的“.NET中的简单中介实现,没有依赖关系的进程内消息传递。通过C#泛型方差支持请求/响应,命令,查询,通知和事件,同步和异步与智能调度。”。这里推荐一款插件Dnspy可以查看dll的源码,这样就可以知道我们所使用的的插件的原理了。

         这里先建好一个.Net Core程序,。然后程序入口处注入MeditaR

services.AddMediatR(typeof(Startup));  //注册发布订阅中介处理

   services.AddScoped<IMediatorHandler,MediatorHandler>();

   services.AddScoped<IRequestHandler<CreateUserCommand, Unit>, UserCommandHandler>();

      对于中介,肯定要先做一个中介处理器,因为程序是面向接口的,所以先定义一个接口,用来表示中介处理器

///     /// 中介处理接口    ///    public interface IMediatorHandler    {        ///         /// 发送领域事件        ///         /// 
/// ///
Task SendCommand
(T command) where T :Command; }

     然后就是它的实现类

public class MediatorHandler: IMediatorHandler    {        private readonly IMediator _mediator;        public InMemoryBus(IMediator mediator)        {            _mediator = mediator;        }        ///         /// 发送邻域事件        ///         /// 
/// ///
public Task SendCommand
(T command) where T : Command { try { return _mediator.Send(command); } catch (AggregateException ex) { throw ex; } } }

这里我们用到了IMediator,我们可以根据Dnspy这个工具查看到IMediator 的Send的方法的实现,

// MediatR.Mediator// Token: 0x06000018 RID: 24 RVA: 0x00002100 File Offset: 0x00000300public Task
Send
(IRequest
request, CancellationToken cancellationToken = default(CancellationToken)){ if (request == null) { throw new ArgumentNullException("request"); } Type requestType = request.GetType(); return ((RequestHandlerWrapper
)Mediator._requestHandlers.GetOrAdd(requestType, (Type t) => Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<, >).MakeGenericType(new Type[] { requestType, typeof(TResponse) })))).Handle(request, cancellationToken, this._serviceFactory);}

    首先我们看到它的参数IRequest<TResponse> request,所以我们可以知道Task SendCommand<T>(T command),这个方法的T一定是继层自IRequest,所以需要我们写一个基类继层于IRequest

///     /// 领域命令基类    ///    public class Command:IRequest    {    } ///     /// 创建用户领域命令    ///     public class CreateUserCommand: Command    {        public CreateUserCommand(User user)        {            User = user;        }        public User User { get; private set; }    }

    因为项目需要添加功能,好比注册一个用户,所以有一个添加用户的Service代码,然后在构造函数里注入IMediatorHandler

public class UserService :IUserService    {        private readonly IUserRepository _userRepository;        private readonly IMediatorHandler _mediatorHandler;        public UserService(IUserRepository userRepository, IMediatorHandler mediatorHandler)        {            _userRepository = userRepository;            _mediatorHandler = mediatorHandler;        }        public void Insert(User user)        {            var command = new CreateUserCommand(user);            try            {                Task task = _mediatorHandler.SendCommand(command);                Task.WaitAll(task);            }            catch (AggregateException)            {                throw new FrameworkException("程序内部错误");            }        }           }
public class UserCommandHandler : IRequestHandler
{ private readonly IUserRepository _userRepository; private readonly IMediatorHandler _mediatorHandler; public UserCommandHandler(IUserRepository userRepository, IMediatorHandler mediatorHandler) { _userRepository = userRepository; _mediatorHandler = mediatorHandler; } public Task
Handle(CreateUserCommand command, CancellationToken cancellationToken) { _userRepository.Insert(command.User); return Task.FromResult(new Unit()); } }
 

 

 

       到这里可以说已经完成了,可以执行了,这样的例子网上也有很多。但是还是需要去了解它的源码,但是自己目前自己只是读懂了源码的20%左右,根据我的理解就是我们在调用IMediator的Send方法时,线程安全集合_requestHandlers会把我们的请求添加到内存里面,具体的就是CreateInstance一个RequestHandlerWrapperImpl对象,但是通过MakeGenericType把它的类型变成了我们请求的类型和返回的类型,然后通过(RequestHandlerWrapper<TResponse>)将Mediator转换类型调用Handler,继续执行RequestHandlerWrapper的实现类RequestHandlerWrapperImpl,然后通过某种方式调用了IRequestHandler,然后找到IRequestHandler的实现类UserCommandHandler,从而完成添加功能。

   无奈自己才疏学浅,并没有理解作者的意思。我现在还是有很多疑问。

,以下是我自认为比较重要的的位置了:

 1 ,这个类我删了很多代码,只留了我们用的到的 Send方法MediatorHandler类里面用到的

public class Mediator : IMediator    {        // Token: 0x06000017 RID: 23 RVA: 0x000020F1 File Offset: 0x000002F1        public Mediator(ServiceFactory serviceFactory)        {            this._serviceFactory = serviceFactory;        }        // Token: 0x06000018 RID: 24 RVA: 0x00002100 File Offset: 0x00000300        public Task
Send
(IRequest
request, CancellationToken cancellationToken = default(CancellationToken)) { if (request == null) { throw new ArgumentNullException("request"); } Type requestType = request.GetType(); return ((RequestHandlerWrapper
)Mediator._requestHandlers.GetOrAdd(requestType, (Type t) => Activator.CreateInstance(typeof(RequestHandlerWrapperImpl<, >).MakeGenericType(new Type[] { requestType, typeof(TResponse) })))).Handle(request, cancellationToken, this._serviceFactory); } // Token: 0x04000001 RID: 1 private readonly ServiceFactory _serviceFactory; // Token: 0x04000002 RID: 2 private static readonly ConcurrentDictionary
_requestHandlers = new ConcurrentDictionary
(); }

   2,

public interface IPipelineBehavior
{ // Token: 0x0600000C RID: 12 Task
Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate
next); }

 3

internal abstract class RequestHandlerWrapper
: RequestHandlerBase { public abstract Task
Handle(IRequest
request, CancellationToken cancellationToken, ServiceFactory serviceFactory); } internal class RequestHandlerWrapperImpl
: RequestHandlerWrapper
where TRequest : IRequest
{ public override Task
Handle(IRequest
request, CancellationToken cancellationToken, ServiceFactory serviceFactory) { Task
Handler() => GetHandler
>(serviceFactory).Handle((TRequest) request, cancellationToken); return serviceFactory .GetInstances
>() .Reverse() .Aggregate((RequestHandlerDelegate
) Handler, (next, pipeline) => () => pipeline.Handle((TRequest)request, cancellationToken, next))(); } }

   4,

public abstract class RequestHandler
: IRequestHandler
, IRequestHandler
where TRequest : IRequest { // Token: 0x06000014 RID: 20 RVA: 0x000020DB File Offset: 0x000002DB Task
IRequestHandler
.Handle(TRequest request, CancellationToken cancellationToken) { this.Handle(request); return Unit.Task; } // Token: 0x06000015 RID: 21 protected abstract void Handle(TRequest request); }

4

转载于:https://www.cnblogs.com/MrHanBlog/p/11309336.html

你可能感兴趣的文章
自己有碗饭吃的想法
查看>>
spring事务源码分析结合mybatis源码(二)
查看>>
乔布斯不在了,世界一大步,苹果一小步。
查看>>
第一节 信息化知识
查看>>
maven环境变量配置
查看>>
poj2245
查看>>
javaScript对象及初识面向对象
查看>>
python+selenium,实现带有验证码的自动化登录功能
查看>>
C语言文件路径中的”/“和“\“
查看>>
VGA接口一根针折了
查看>>
vue生命周期
查看>>
一种快速部署开发用oracle的办法
查看>>
面试-框架篇
查看>>
程序过程简单总结
查看>>
第十二周作业
查看>>
用一条mysql语句插入多条数据
查看>>
在Azure Cloud Service中部署Java Web App(1)
查看>>
Git学习03-----最基本的几个命令
查看>>
maven00----maven学习说明
查看>>
IIS搭建站点错误系列
查看>>