【.NET后端工具系列】MediatR实现进程内消息通讯

阅读本文你的收获

  1. 学习MediatR工具,实现进程内消息发送和处理过程的解耦
  2. 学习MediatR的两种消息处理模式
  3. 了解中介者模式和其好处

一、什么是MediatR?

MediatR是一款基于中介者模式的思想而实现的.NET库,支持.NET Framework和跨平台 的.NET Core。主要是为了解决进程内消息发送与消息处理过程之间的耦合问题。MediatR的作者是Jimmy Bogard,如果你不知道这个人,想必你也用过他开发的AutoMapper吧。

它通过一种进程内消息传递机制(无其他外部依赖),进行请求/响应、命令、查询、通知和事件的消息传递,并通过泛型来支持消息的智能调度。

MediatR有两种消息处理模式:

  • Request/Response模式:请求响应模式,一对一,消息(Message)将被单个处理者(Handler)处理,可以有返回值
  • Notifictaion模式:发布订阅模式,一对多,Message可以被多个Handler处理,无返回值

二、中介者模式介绍

为什么使用中介者模式?

在现实生活中,中介者的存在是不可缺少的,比如房屋中介、招聘平台等;网络世界中有很多中介者模式的身影,例如QQ游戏平台,聊天室、QQ群和短信平台

在软件设计领域,为什么要使用中介者模式呢?如果不使用中介者模式的话,各个同事对象将会相互进行引用,如果每个对象都与多个对象进行交互时,将会形成如下图所示的网状结构。
多对象交互网状结构
从上图可以发现,如果不使用中介者模式的话,每个对象之间过度耦合,这样的既不利于类的复用也不利于扩展。如果引入了中介者模式,那么对象之间的关系将变成星型结构,采用中介者模式之后会形成如下图所示的结构:
中介者模式
中介者模式使之前的网状结构,现在变成了以中介者为中心的星星结构。这样的设计大大减少了系统的耦合度。

中介者就像一个容器的,它自己把控着整个流程,和每一个对象都有或多或少,或近或远的联系,多个对象之间不用理睬其他对象发生了什么,只是负责自己的模块就好,然后把消息发给中介者,让中介者再分发给其他的具体对象,从而实现通讯 —— 这个思想就是中介者的核心思想,而且也是DDD领域驱动设计的核心思想之一。

中介者模式是23种设计模式之一?

中介者模式是23种设计模式的其中一个。中介者模式是一个行为设计模式,它允许我们公开一个统一的接口,系统的 不同部分 可以通过该接口进行 通信,而 不需要 显式的相互作用; 类图结构如下:
中介者模式类图
中介者使各个对象不需要显式地相互引用,从而使其耦合性降低,而且可以独立地改变它们之间的交互。

以下情况下可考虑使用中介者模式:

  • 一组定义良好的对象之间需要进行通信的场合
  • 想通过一个中间类来封装多个类中的行为,而又不想生成太多的子类。

以下是一个具体例子,联合国就是一个中介者:
联合国

三、MediatR的应用场景

以下是 MediatR 的一些适用场景:

  • CQRS(Command and Query Responsibility Segregation,命令查询责任分离):MediatR 可以用于实现 CQRS 架构的命令与查询分离。通过将命令和查询封装为不同的请求对象,并使用中介者模式来处理这些请求,可以更好地组织和管理复杂的业务逻辑。
  • 事件驱动架构(Event-Driven Architecture):MediatR 可以用于实现事件的发布和订阅模式。通过定义和处理事件通知,可以实现松耦合的组件间通信,以及更灵活的系统扩展和异步处理。
  • 插件化和扩展性:MediatR 可以用于实现插件化和可扩展的应用程序架构。通过定义通用的请求和处理逻辑,并利用中介者模式将请求和处理解耦,可以方便地添加、移除和替换各种功能模块。
  • 视图模型更新(View Model Updates):MediatR 可以用于处理视图模型的更新操作。通过定义更新请求和相应的处理器,可以实现对视图模型的增、删、改等操作,并在更新完成后及时通知相关组件进行界面更新。
  • 领域事件和领域命令:MediatR 可以用于处理领域事件和领域命令。通过定义相应的事件和命令,并使用中介者模式进行处理,可以有效地组织和管理领域逻辑,并实现解耦、可测试和可扩展的领域模型。

总体而言,MediatR适用于需要解耦请求和处理逻辑的场景,能够提高代码的可读性、可维护性和可扩展性。它可以与其他架构模式(如CQRS、事件驱动架构等)结合使用,以满足不同的业务需求和系统设计要求。

四、MediatR使用入门

开发环境:

平台版本是:.NET6
开发框架:ASP.NET Core WebApi
开发工具:Visual Studio 2022

  1. 引用MediatR的NuGet包,案例版本为11.0.0
    添加MediatR

3.1 演示 request/response 请求响应模式

此案例,演示一个游戏管理模块的“添加游戏”这个功能。

  1. 步骤一:创建一个“”添加游戏”请求消息类,需要实现IRequest,或IRequest< T > 接口
//引用命名空间
using MediatR;namespace MediatRWebApp.Requests
{//Request类,string是处理者响应的数据类型public class AddGameRequest : IRequest<string>{public int GameId { get; set; }         public string GameName { get; set; }public string GameType { get; set; }}
}
  1. 步骤二:创建一个消息处理器对象,需实现 IRequestHandler<AddGameRequest , string>接口
using MediatR;
using MediatRWebApp.Requests;namespace MediatRWebApp.RequestHandlers
{//Handler类型,PingRequest是其处理的请求类型,string是处理者响应的数据类型public class AddGameRequestHandler : IRequestHandler<AddGameRequest, string>{/// <summary>/// 处理AddGameRequest请求,返回string类型的响应/// </summary>/// <param name="request">请求对象</param>/// <param name="cancellationToken">取消令牌</param>/// <returns></returns>public Task<string> Handle(AddGameRequest request, CancellationToken cancellationToken){//做如下的一些处理:(代码略)//验证输入的参数是否正确//可能还要做名称的唯一性判断//根据Request来创建一个实体对象//用仓储把他保存到数据库中return Task.FromResult("添加游戏成功!");}}
}

步骤三:在服务容器中注册AddGameRequestHandler

using MediatR;
using MediatRWebApp.RequestHandlers;//在Program.cs 注册AddGameRequestHandler 
builder.Services.AddMediatR(typeof(AddGameRequestHandler ));

步骤四:在控制器方法中用Mediator的Send方法发送请求,对应的Request请求将由注册过的Handler来处理。

//在控制器中使用
using MediatR;
using MediatRWebApp.Requests;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;namespace MediatRWebApp.Controllers
{[Route("api/[controller]")][ApiController]public class GameController : ControllerBase{//构造函数注入Mediatorprivate readonly IMediator _mediator;//构造方法public GameController(IMediator mediator){_mediator = mediator;}/// <summary>/// 添加游戏的接口方法/// </summary>/// <returns></returns>[HttpPost]public async Task<IActionResult> Add([FromBody]AddGameDto input){AddGameRequest request = new AddGameRequest (){GameName = input.GameName,GameType = input.GameType };var response  =  await _mediator.Send(request);return Ok(response);}}
}

3.2 演示 Notification 发布/订阅模式:

  1. 步骤一:创建一个通知对象,必须继承INotification接口
using MediatR;public class DomainNotification: INotification
{public DomainNotification(string message){Message = message;}public string Message { get; set; }  //通知的消息
}
  1. 步骤二:创建两个消息处理器
//步骤二:创建一个消息处理器
public class DomainNotificationHandler : INotificationHandler<DomainNotification>
{/// <summary>/// 处理消息/// </summary>/// <param name="notification"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task Handle(DomainNotification notification, CancellationToken cancellationToken){Console.WriteLine("{0} 被消息处理器DomainNotificationHandler处理了!!", notification.Message);return  Task.CompletedTask;}
}//步骤二:创建另一个消息处理器
public class AnotherNotificationHandler : INotificationHandler<DomainNotification>
{/// <summary>/// 处理消息/// </summary>/// <param name="notification"></param>/// <param name="cancellationToken"></param>/// <returns></returns>public Task Handle(DomainNotification notification, CancellationToken cancellationToken){Console.WriteLine("{0} 被消息处理器AnotherNotificationHandler处理了!!", notification.Message);return Task.CompletedTask;}
}
  1. 步骤三:通过 中介者对象 发布通知消息(发布订阅模式)
using MediatR;
using MediatRWebApp.Notifications;
using MediatRWebApp.Requests;[Route("api/[controller]")][ApiController]public class PingController : ControllerBase{private readonly IMediator _mediator;//构造方法public PingController (IMediator mediator){_mediator = mediator;}/// <summary>///  测试方法/// </summary>/// <returns></returns>[HttpPost]public async Task<IActionResult> TestNotification(){//发送请求消息 PingRequestvar response = await _mediator.Send(new PingRequest());//将通知消息广播出去,订阅了DomainNotification的Handler都能够响应await _mediator.Publish(new DomainNotification("添加成功"));return Ok(response);}}

本文到此结束,欢迎各位的支持和鼓励,如果对你有帮助的话,请点赞+关注,或者转发给需要的朋友。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/235883.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

aws配置以及下载 spaceNet6 数据集

一&#xff1a;注册亚马逊账号 注册的时候&#xff0c;唯一需要注意的是信用卡绑定&#xff0c;这个可以去淘宝买&#xff0c;搜索aws匿名卡。 注册完记得点击登录&#xff0c;记录一下自己的账户ID哦&#xff01; 二&#xff1a;登录自己的aws账号 2.1 首先创建一个用户 首…

从YOLOv1到YOLOv8的YOLO系列最新综述【2023年4月】

作者&#xff1a;Juan R. Terven 、Diana M. Cordova-Esparaza 摘要&#xff1a;YOLO已经成为机器人、无人驾驶汽车和视频监控应用的核心实时物体检测系统。我们对YOLO的演变进行了全面的分析&#xff0c;研究了从最初的YOLO到YOLOv8每次迭代的创新和贡献。我们首先描述了标准…

研发管理-代码管理篇

前言&#xff1a; 工作了这些年&#xff0c;工作了三家公司&#xff0c;也用过主流的代码管理平台&#xff0c;比如SVN&#xff0c;git系列&#xff08;gitlib,gitee&#xff09;,各有优点&#xff0c;我个人比较喜欢SVN&#xff0c;多人协作的代码管理难免会有代码冲突&#…

2024年【北京市安全员-B证】考试试卷及北京市安全员-B证复审模拟考试

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 北京市安全员-B证考试试卷根据新北京市安全员-B证考试大纲要求&#xff0c;安全生产模拟考试一点通将北京市安全员-B证模拟考试试题进行汇编&#xff0c;组成一套北京市安全员-B证全真模拟考试试题&#xff0c;学员可…

深入了解 npm 命令

目录 前言1 初始化项目2 安装依赖3 更新依赖4 发布包5 卸载包6 查看依赖7 运行脚本8 包搜索9 查看包信息结语 前言 在现代 Web 开发中&#xff0c;JavaScript 是一种至关重要的语言&#xff0c;而 npm&#xff08;Node Package Manager&#xff09;作为 Node.js 平台的默认软件…

ChatGPT如何计算token数?

GPT 不是适用于某一门语言的大型语言模型&#xff0c;它适用于几乎所有流行的自然语言。所以 GPT 的 token 需要 兼容 几乎人类的所有自然语言&#xff0c;那意味着 GPT 有一个非常全的 token 词汇表&#xff0c;它能表达出所有人类的自然语言。如何实现这个目的呢&#xff1f;…

SparkSQL读写数据

1.3 SparkSQL读写数据 1.3.1 数据的加载 Sparksql中加载外部的数据&#xff0c;使用统一的API入口&#xff0c; spark.read.format(数据文件格式).load(path) 这个方式有更加清晰的简写方式&#xff0c;比如要加载json格式的文件 spark.read.json(path) 默认加载的文件格式为…

BSWM 模式管理(一) 基本规则

BSWM 模式管理 基本规则 1 BSWM 模式管理2 AUTOSAR BSWM 的两种 operation 模式2.1 deferred opration2.2 immediate opration1 BSWM 模式管理 BSW 模式管理由 4 部分组成: Mode source: 模式仲裁的的触发器,可以由 APP/BSW 模块请求触发Mode Arbitration:当模式源出发的时候…

全球知名的五款JavaScript混淆加密工具详解

​ 现在市场上有很多好用的混淆加密工具&#xff0c;其中一些比较流行且受欢迎的工具包括&#xff1a; 1、UglifyJS&#xff08;罗马尼亚&#xff09;&#xff1a;UglifyJS是一个非常流行的 JavaScript工具库&#xff0c;它可以压缩、混淆、美化和格式化 JavaScript 代码。使用…

线程学习(2)

&#x1f495;"i need your breath"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;线程学习(2) 前情回顾&#xff1a; 在上一篇博客中介绍到了进程与线程的区别&#xff0c;以及初步了解如何在Java实现多线程编程&#xff0c;通过内置的Thread类来…

Python发送邮件

Python发送邮件 一、概念二、邮件服务器设置三、发送邮件流程3.1 登录邮箱3.2 准备数据3.3 发送邮件 四、实现4.1 发送文本4.2 发送html4.3 发送图片4.4 发送文件 一、概念 SMTP(Simple Mail Transfer Protocol)&#xff0c;即简单邮件传输协议,它是一组用于由源地址到目的地址…

自定义 spring-boot组件自动注入starter

1&#xff1a;创建maven项目 2&#xff1a;pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocati…

Jenkins + gitlab 持续集成和持续部署的学习笔记

1. Jenkins 介绍 软件开发生命周期(SLDC, Software Development Life Cycle)&#xff1a;它集合了计划、开发、测试、部署的集合。 软件开发瀑布模型 软件的敏捷开发 1.1 持续集成 持续集成 (Continuous integration 简称 CI): 指的是频繁的将代码集成到主干。 持续集成的流…

全光谱护眼灯哪个牌子好?全光谱备考护眼台灯推荐

什么是全光谱&#xff1f;全光谱指的是光谱中包含紫外光、可见光、红外光的光谱曲线&#xff0c;并且在可见光部分中红绿蓝的比例与阳光近似&#xff0c;显色指数接近于100的光谱。太阳光的光谱可以称作全光谱&#xff0c;太阳光的色温是随着四季和早晚时间变化而变化&#xff…

SD 一次性客户地址如何打开

一次性客户 写入后在哪里看具体数据呢 在转到->抬头->合作伙伴 双击Y0

基于EasyDarwin、ffmpeg实现rtsp推流

目录 1 安装EasyDarwin 2 编译安装ffmpeg 3 启动EasyDarwin 4 ffmepg推流 5 百度网盘备份 某项目中测试时需要用到推流&#xff0c;于是用EasyDarwin、ffmpeg实现了RTSP推流&#xff0c;简单记录下过程&#xff0c; 1 安装EasyDarwin 这个可以去官网下载&#xff1a;Eas…

大模型互相“薅羊毛”背后,行业基本操作,规范化势在必行

最近&#xff0c;字节跳动被曝调用 OpenAI API 接口训练大模型的争议&#xff0c;以及谷歌大模型 Gemini 被曝使用百度文心一言进行中文语料训练等事件&#xff0c;在行业里引发了不小的关注和讨论。 不明真相的网友们一边热情吃瓜&#xff0c;一边也在感叹 AI 大厂之间互相“…

【论文解读】Efficient SAO Coding Algorithm for x265 Encoder

时间&#xff1a;2015年 级别&#xff1a;IEEE 机构&#xff1a;上海交通大学 摘要 x265是一款开源的HEVC编码器&#xff0c;采用了多种优化技术&#xff0c;具有较快的编码速度和优良的编码性能。作为HEVC的一项关键技术&#xff0c;x265还采用了样本自适应偏移(sample adap…

工作流引擎的架构设计与对比

所谓工作流引擎是指 workflow 作为应用系统的一部分&#xff0c;并为之提供对各应用系统有决定作用的&#xff0c;根据角色、分工和条件的不同决定信息传递路由、内容等级 等核心解决方案。工作流引擎可以灵活地配置工作流程&#xff0c;并且可以自动化的根据配置进行状态变更和…

WebRPC开发基础流程

一、WebRTC 使用入门 WebRTC&#xff08;全称 Web Real-Time Communication&#xff09;&#xff0c;即网页即时通信。 是一个支持网页浏览器进行实时语音对话或视频对话的技术方案。从前端技术开发的视角来看&#xff0c;是一组可调用的API标准。 WebRTC API 官网&#xff1…