zoukankan      html  css  js  c++  java
  • 一起来学习.net core程序使用中介者模式:MediatR插件

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

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

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

      services.AddMediatR(typeof(Startup));

    //注册发布订阅中介处理

       services.AddScoped<IMediatorHandler,MediatorHandler>();

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

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

        /// <summary>
        /// 中介处理接口
        /// </summary>
       public interface IMediatorHandler
        {
            /// <summary>
            /// 发送领域事件
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="command"></param>
            /// <returns></returns>
            Task SendCommand<T>(T command) where T :Command;
        }

         然后就是它的实现类

        public class MediatorHandler: IMediatorHandler
        {
            private readonly IMediator _mediator;
            public InMemoryBus(IMediator mediator)
            {
                _mediator = mediator;
            }
            /// <summary>
            /// 发送邻域事件
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="command"></param>
            /// <returns></returns>
            public Task SendCommand<T>(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: 0x00000300
    public Task<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default(CancellationToken))
    {
        if (request == null)
        {
            throw new ArgumentNullException("request");
        }
        Type requestType = request.GetType();
        return ((RequestHandlerWrapper<TResponse>)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

     
     /// <summary>
        /// 领域命令基类
        /// </summary>
       public class Command:IRequest
        {
        }
     /// <summary>
        /// 创建用户领域命令
        /// </summary>
        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<CreateUserCommand, Unit>
        {
            private readonly IUserRepository _userRepository;
            private readonly IMediatorHandler _mediatorHandler;
            public UserCommandHandler(IUserRepository userRepository, IMediatorHandler mediatorHandler)
            {
                _userRepository = userRepository;
                _mediatorHandler = mediatorHandler;
            }
            public Task<Unit> 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<TResponse> Send<TResponse>(IRequest<TResponse> request, CancellationToken cancellationToken = default(CancellationToken))
            {
                if (request == null)
                {
                    throw new ArgumentNullException("request");
                }
                Type requestType = request.GetType();
                return ((RequestHandlerWrapper<TResponse>)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<Type, object> _requestHandlers = new ConcurrentDictionary<Type, object>();
    
        }

       2,

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

     3

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

       4,

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

    4

  • 相关阅读:
    Moya 浅析
    Swift: Alamofire -> http请求 & ObjectMapper -> 解析JSON
    ReactiveCocoa 用法实例
    RACSignal的Subscription深入
    idea 不能编译生成class文件
    idea 右下角不显示git分支
    SSO单点登录的研究
    JVM内存模型简介
    Spring事务处理
    RabbitMQ
  • 原文地址:https://www.cnblogs.com/MrHanBlog/p/11309336.html
Copyright © 2011-2022 走看看