首页 > 编程语言 >一起来学习.net core程序使用中介者模式:MediatR插件

一起来学习.net core程序使用中介者模式:MediatR插件

时间:2024-08-28 10:48:31浏览次数:8  
标签:core 插件 Task Handle MediatR cancellationToken serviceFactory request public

一起来学习.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

标签:core,插件,Task,Handle,MediatR,cancellationToken,serviceFactory,request,public
From: https://www.cnblogs.com/sexintercourse/p/18384153

相关文章

  • 金蝶云星空插件引入
    1、‌金蝶云星空中使用StringBuilder需要引入System.Text命名空间fromSystem.Textimport*......
  • CoreShop---.NET、Uni-App开发支持多平台的小程序商城系统
    前言小程序商城系统是当前备受追捧的开发领域,它可以为用户提供一个更加便捷、流畅、直观的购物体验,无需下载和安装,随时随地轻松使用。今天给大家推荐一个基于.NET、Uni-App开发支持多平台的小程序商城系统(该商城系统完整开源、无封装无加密、商用免费、支持二次开发、支持跨平台......
  • ComfyUI-插件IPAdapter图片融合(附插件)
    哈喽大家好,前两期介绍了IPAdapter的风格迁移和人物形象迁移,这期来分享下如何利用IPAdapter实现两张图的融合参考图1参考图2融合图图片融合1、工作流将基础工作流中的【IPAdapterUnifiedLoader】节点换成【IPAdapterUnifiedLoaderCommunity】【IPAdapter】节......
  • 【Mybatis-Plus】防全表更新与删除插件
    From: https://baomidou.com/plugins/block-attack/BlockAttackInnerInterceptor 是MyBatis-Plus框架提供的一个安全插件,专门用于防止恶意的全表更新和删除操作。该插件通过拦截 update 和 delete 语句,确保这些操作不会无意中影响到整个数据表,从而保护数据的完整性和安全......
  • .NET Core 处理 WebAPI JSON 返回烦人的null为空
    前言   项目开发中不管是前台还是后台都会遇到烦人的null,数据库表中字段允许空值,则代码实体类中对应的字段类型为可空类型Nullable<>,如int?,DateTime?,null值字段序列化返回的值都为null,前台对应字段赋值需要做null值判断,怎么才能全局把null替换为空。    本文分享Web......
  • mitk添加插件步骤
    一插件添加说明在MITK(MedicalImagingInteractionToolkit)中添加一个插件涉及多个步骤。以下是一个基本的指南,帮助你在MITK中添加插件:1.**设置开发环境**:  -确保已安装必要的开发工具,例如CMake和一个兼容的C++编译器。  -下载并构建MITK的源代码。这通......
  • mitk插件有哪些以及作用
    MITK(MedicalImagingInteractionToolkit)是一个用于医疗图像处理与交互的开源软件框架。它提供了一套丰富的插件,使其功能得到扩展和定制。以下是一些常见的MITK插件及其作用:1.**DICOM支持插件**:  -**作用**:提供对DICOM(DigitalImagingandCommunicationsinMedic......
  • neovim 安装插件,并配置vimconig
    neovim安装插件,并配置vimconig1.neovim安装参考这里2.插件包管理器安装Vundle是vim的一个插件管理器,同时它本身也是vim的一个插件。插件管理器用于方便、快速的安装、删除、Vim更新插件。vimVundle插件官方地址:https://github.com/VundleVim/Vundle.vim下载Vundle插件......
  • vue3uniapps使用富文本mp-html插件
    1.实现效果具体需求:顶部是搜索栏,包括搜索结果个数,目前跳到第几个,包含上一个、下一个按钮。富文本区域关键词高亮黄色,当前关键词为高亮橙色。如图2.版本号用到vue3和uniapp,mp-html插件版本是v2.5.0,插件地址:https://ext.dcloud.net.cn/plugin?id=805用npm方式打包放到......
  • auto_size_text 自动调整文本大小以适应其容器的 Flutter 插件
    依赖auto_size_text:^3.0.0//自动调整文本大小例子classAutoSizeRichTextExampleextendsStatelessWidget{@overrideWidgetbuild(BuildContextcontext){returnCenter(child:Container(width:double.infinity,child:AutoSi......