MediatR 框架使用FluentValidation对Comand/Query进行自动拦截验证
简介
目录
简介
1. MediatR项目框架
2. 实现步骤
步骤 1:编写管道行为
1. query 查询的管道
2. command命令的管道
步骤 2:注册验证器和管道行为
步骤 3:定义命令类
步骤 4:定义处理程序
步骤 5:编写命令验证器
步骤 6:使用方法
3. 总结
在使用 MediatR 框架时,我们经常需要对命令对象进行验证。为了实现自动验证,我们可以使用 MediatR 的管道行为在命令处理之前执行验证逻辑。本文档将介绍如何在控制器外部使用 MediatR 的管道行为来自动验证实现了 ICommand/IRequest 接口的类,并提供正确地注册验证器和管道行为的方法。
1. MediatR项目框架
使用Mediator来构建项目框架具有一系列的优点和缺点。以下是对这些优缺点的详细分析:
优点:
- 解耦与简化通信:Mediator架构的核心思想是通过一个中介者对象来管理系统中各个组件之间的交互,从而实现了对象之间的解耦。这使得组件之间的通信更加简单,降低了系统的复杂性,提高了代码的可读性和可维护性。
- 易于扩展和修改:由于系统的组件之间是通过中介者进行通信的,因此当需要添加或删除组件时,只需要修改中介者的代码,而不需要修改其他组件的代码。这使得系统的扩展和修改变得更加容易。
- 集中控制:中介者对象可以集中控制组件之间的交互,确保它们按照预定的规则进行通信。这有助于减少系统中的错误和冲突,提高系统的稳定性和可靠性。
缺点:
- 性能开销:由于所有的组件都通过中介者进行通信,这可能会导致一定的性能开销。特别是在处理大量消息或复杂交互时,中介者可能成为性能瓶颈。
- 过度依赖中介者:如果系统过度依赖中介者对象,那么中介者的设计和实现可能会变得非常复杂。一旦中介者出现问题,整个系统可能会受到影响。
- 不适用于所有场景:虽然Mediator架构在某些场景下非常有用,但它并不适用于所有类型的项目。在某些情况下,使用其他架构可能更为合适。
ProductManage/
│
├── Controllers/ // 控制器文件夹
│ └── ProductController.cs
│
├── Models/ // 模型文件夹
│ └── Product.cs
│
├── Application/ // 应用层文件夹
│ ├── Commands/ // 命令文件夹
│ │ └── CreateProductCommand.cs
│ │
│ ├── Queries/ // 查询文件夹
│ │ └── GetProductQuery.cs
│ │
│ └── Handlers/ // 处理程序文件夹
│ ├── CreateProductCommandHandler.cs
│ └── GetProductQueryHandler.cs
│
├── Infrastructure/ // 基础设施层文件夹
│ └── Persistence/ // 持久化文件夹
│ └── DbContext.cs
│
├── Domain/ // 领域层文件夹
│ └── Entities/ // 实体文件夹
│ └── Product.cs
│
├── Validators/ // 验证器文件夹
│ └── CreateProductCommandValidator.cs
│
└── Startup.cs // 启动文件
2. 实现步骤
步骤 1:编写管道行为
编写一个管道行为来执行验证逻辑,这个管道行为将在命令处理之前执行验证。由于ICommand继承自IRequest接口,所以只需要添加IRequest管道拦截器
using FluentValidation;
using MediatR;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
public class ValidationQueryBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>where TRequest : IRequest<TResponse>
{private readonly IEnumerable<IValidator<TRequest>> _validators;public ValidationQueryBehavior(IEnumerable<IValidator<TRequest>> validators){_validators = validators;}public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken){// 执行所有验证器var failures = _validators.Select(v => v.Validate(request)).SelectMany(result => result.Errors).Where(error => error != null).ToList();var failuresAsync = _validators.Select(async v => await v.ValidateAsync(request)).SelectMany(result => result.Result.Errors).Where(error => error != null).ToList();failures.AddRange(failuresAsync);if (failures.Any()){throw new DecBussinessExpection(failures.FirstOrDefault().ErrorMessage, Convert.ToInt32(failures.FirstOrDefault().ErrorCode));}// 如果通过验证,则继续执行下一个处理程序return await next();}}
步骤 2:注册验证器和管道行为
接下来,我们需要将验证器和管道行为注册到 DI 容器中,以便在 MediatR 的管道中使用它们进行自动验证。
using FluentValidation.AspNetCore;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using System.Reflection;public class Startup
{public void ConfigureServices(IServiceCollection services){var assemblies = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "ProductManage.Application.*.dll", SearchOption.TopDirectoryOnly).Select(Assembly.LoadFrom).ToArray();// 注册 MediatRbuilder.Services.AddMediatR(assemblies);// 注册 FluentValidation 验证器builder.Services.AddValidatorsFromAssemblies(assemblies).AddFluentValidationAutoValidation().AddFluentValidationClientsideAdapters().AddMemoryCache().AddRuleEngine();// 注册管道行为builder.Services.AddTransient(typeof(IPipelineBehavior<,>), typeof(ValidationQueryBehavior<,>));}
}
步骤 3:定义命令类
我们需要定义一个实现了 ICommand 接口的命令类。这个命令类将在 MediatR 管道中被自动验证。
public class CreateProductCommand : ICommand<ProductDTO>
{public string Name { get; set; }public decimal Price { get; set; }
}
步骤 4:定义处理程序
定义一个实现ICommandHandler接口的处理程序类,该类主要实现业务逻辑。
public class CreateProductHandler : ICommandHandler<CreateProductCommand, ProductDto>{public Task<ProductDto> Handle(CreateProductCommand request, CancellationToken cancellationToken){//实现业务逻辑}}
步骤 5:编写命令验证器
然后,我们需要编写一个验证器来验证命令类。这个验证器将使用 FluentValidation 等验证库来定义验证规则。
using FluentValidation;public class CreateProductCommandValidator : AbstractValidator<CreateProductCommand>
{private IProductService _productService;public CreateProductCommandValidator(IProductService productService){ _productService=productService;}public override async Task<ValidationResult> ValidateAsync(ValidationContext<CreateProductCommand> context, CancellationToken cancellation = default){RuleFor(it => it.Name).NotNull().CustomException(CustomerErrorMsg.名称不能为空);var command = context.InstanceToValidate;if (await _decCustomerMainService.CheckData()){return new ValidationResult(new[] { new CustomValidationFailure(ProductErrorMsg.该商品不存在) });}return await base.ValidateAsync(context, cancellation);}
}
步骤 6:使用方法
[HttpPost()]public async Task<ApiResponse<ProductDTO>> Create(CreateProductReq requestDto){var productInfo= await _mediator.Send(new CreateProductCommand(requestDto));return new ApiResponse<ProductDTO>() { Code = (int)ApiErrorCode.成功, Message = "成功", Result = productInfo};}
3. 总结
通过以上步骤,我们成功地实现了在控制器外部使用 MediatR 的管道行为来自动验证实现了 ICommand 接口的类。首先,我们定义了命令类和命令验证器。然后,我们注册了验证器和管道行为到 DI 容器中,并编写了管道行为来执行验证逻辑。最终,我们可以在控制器中发送命令,而管道行为会自动执行验证逻辑,并在需要时抛出验证异常。
注:控制器方法参数,FluentValidation会自动拦截验证,不需要额外的在管道里配置拦截验证。
相关文章:
MediatR 框架使用FluentValidation对Comand/Query进行自动拦截验证
简介 目录 简介 1. MediatR项目框架 2. 实现步骤 步骤 1:编写管道行为 1. query 查询的管道 2. command命令的管道 步骤 2:注册验证器和管道行为 步骤 3:定义命令类 步骤 4:定义处理程序 步骤 5:编写命令验证器…...
TS + Vue3 elementUI 表格列表中如何方便的标识不同类型的内容,颜色区分 enum
TS Vue3 elementUI 表格列表中如何方便的标识不同类型的内容,颜色区分 enum 本文内容为 TypeScript 一、基础知识 在展示列表的时候,列表中的某个数据可能是一个类别,比如: enum EnumOrderStatus{"未受理" 1,"…...
从零开始一步一步掌握大语言模型---(2-什么是Token?)
了解自然语言处理或者听说过大语言模型的同学都听过,token。一般来说,它代表的是语言中不可再分的最小单元。我们人类的语言不仅有文字,还有语音。针对文字、语音来说,它们都各自有不同的划分token的方法。本节将尽可能详细的介绍…...
使用专属浏览器在国内直连GPT教程
Wildcard官方推特发文说他们最近推出了一款专门为访问OpenAI设计的浏览器。 根据官方消息,这是一款专门为访问OpenAI优选网络设计的浏览器,它通过为用户提供专用的家庭网络出口,确保了快速、稳定的连接。 用这个浏览器的最大好处就是直接用浏…...
Wireshark 抓包工具与长ping工具pinginfoview使用,安装包
一、Wireshark使用 打开软件,选择以太网 1、时间设置时间显示格式 这个时间戳不易直观,我们修改 2、抓包使用的命令 1)IP地址过滤 ip.addr192.168.1.114 //筛选出源IP或者目的IP地址是192.168.1.114的全部数据包。 ip.sr…...
分享Pandas 数据分析实战课程
分享Pandas 数据分析实战课程,3 小时掌握数据分析核心技能。 链接:https://pan.baidu.com/s/1Ikk3I1dfoFO0id3EBZJdGg?pwd4y83 提取码:4y83 链接:https://pan.quark.cn/s/fa2acd7513f4 提取码:yWu7...
26. 删除有序数组中的重复项 (Swift版本)
题目描述 给你一个 非严格递增排列 的数组 nums ,请你删除重复出现的元素,使每个元素只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。 考虑 nums 的唯一元素的数量为 k ࿰…...
python学生作业管理系统flask-django-nodejs-php
课题主要分为三大模块:即管理员模块和学生、教师模块,主要功能包括:学生、教师、作业信息、学习模块、教学评价、学习情况等; 关键词:学生作业管理系统;作业信息 目录 摘 要 I Abstrac II 目录 III 1绪论 1…...
蓝桥杯第二天刷真题
public class Main {public static void main(String [] args) { //存大数方法String s"202320232023"; // 定义一个字符串,它将被转换为结束循环的数值long end Long.parseLong(s);long sum 0;long primarynumber 1;for(int i 1; i<end; i) {long …...
RK3568 安装jupyter和jupyterlab
首先需要RK3568运行Ubuntu,之前的文章有关于如何安装Ubuntu以及遇到的问题 其次需要安装Miniconda3,详细安装教程:RK3568 安装Miniconda3-CSDN博客 准备好这两步之后就可以开始: 1、更新软件源和软件 sudo apt update sudo apt upgrade sudo apt-get dist-upgrade 2、…...
简易指南:国内ip切换手机软件怎么弄
在网络访问受到地域限制的情况下,使用国内IP切换手机软件可以帮助用户轻松访问被屏蔽的内容,扩展网络体验。以下是虎观代理小二分享的使用国内IP切换手机软件的简易指南。并提供一些注意事项。 如何在手机上使用国内IP切换软件 步骤一:选择I…...
Git学习笔记之Git 别名
Git 并不会在你输入部分命令时自动推断出你想要的命令。 如果不想每次都输入完整的 Git 命令,可以通过 git config 文件来轻松地为每一个命令设置一个别名。命令: git config --global alias.别名 命令例如 git config --global alias.co checkout git …...
网络安全笔记-day6,NTFS安全权限
文章目录 NTFS安全权限常用文件系统文件安全权限打开文件安全属性修改文件安全权限1.取消父项继承权限2.添加用户访问权限3.修改用户权限4.验证文件权限5.总结权限 强制继承父项权限文件复制移动权限影响跨分区同分区 总结1.权限累加2.管理员最高权限2.管理员最高权限 NTFS安全…...
云计算系统等保测评对象和指标选取
1、云计算服务模式与控制范围关系 参考GBT22239-2019《基本要求》附录D 云计算应用场景说明。简要理解下图,主要是云计算系统安全保护责任分担原则和云服务模式适用性原则,指导后续的测评对象和指标选取。 2、测评对象选择 测评对象 IaaS模式 PaaS模式…...
Vue 3项目中结合Element Plus的<el-menu>和CSS3创建锚点,以实现点击菜单项时平滑滚动到对应的锚点目标
安装Element Plus: 确保已经安装了Element Plus库。可以使用npm或者yarn进行安装,具体步骤与上文提到的相同。 引入Element Plus: 在你的Vue 3项目中引入所需的Element Plus组件和样式。 创建el-menu: 在Vue组件中使用<el-me…...
C语言:数据在内存中的存储
目录 一、 整数在内存中的存储二、 大小端字节序和字节序判断1.什么是大小端2.为什么有大小端3.练习(1)练习1(2)练习2(3)练习3(4)练习4(5)练习5(6)练习6 三、 浮点数在内存中的存储1.练习2.浮点数的存储(1) 浮点数存的过程(2)浮点数取的过程 3.题目解析 一、 整数在内存中的存储…...
DP动态规划入门(数字三角形、破损的楼梯、安全序列)
一、动态规划(DP)简介 动态规划(Dynamic Programming,简称DP)是运筹学的一个分支,它是一种通过将复杂问题分解成多个重叠的子问题,并通过子问题的解来构建整个问题的解的算法。在动态规划中&am…...
HBase Shell的应用案例
电商( eshop)平台具有海量数据、高并发访问、高速读写等特征,适合使用HBase分布式数据库进行数据存储。本节通过一个 HBase在电商平台的应用案例,熟练掌握并综合运用HBase Shell命令行终端提供的各种操作命令。 一、电商(eshop)平台的逻辑数据模型 在H…...
Allegro许可管理技巧
在数字化时代,软件许可管理对于企业的运营至关重要。然而,许多企业在实施软件管理过程中会遇到各种问题。Allegro许可管理作为一款高效、合规的管理工具,能够帮助企业解决常见的许可管理问题。本文将深入探讨Allegro许可管理中的实用技巧&…...
34 vue 项目默认暴露出去的 public 文件夹 和 CopyWebpackPlugin
前言 这里说一下 vue.config.js 中的一些 public 文件夹是怎么暴露出去的? 我们常见的 CopyWebpackPlugin 是怎么工作的 ? 这个 也是需要 一点一点积累的, 因为 各种插件 有很多, 不过 我们仅仅需要 明白常见的这些事干什么的即可 当然 以下内容会涉及到一部分vue-cli,…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
盘古信息PCB行业解决方案:以全域场景重构,激活智造新未来
一、破局:PCB行业的时代之问 在数字经济蓬勃发展的浪潮中,PCB(印制电路板)作为 “电子产品之母”,其重要性愈发凸显。随着 5G、人工智能等新兴技术的加速渗透,PCB行业面临着前所未有的挑战与机遇。产品迭代…...
R语言AI模型部署方案:精准离线运行详解
R语言AI模型部署方案:精准离线运行详解 一、项目概述 本文将构建一个完整的R语言AI部署解决方案,实现鸢尾花分类模型的训练、保存、离线部署和预测功能。核心特点: 100%离线运行能力自包含环境依赖生产级错误处理跨平台兼容性模型版本管理# 文件结构说明 Iris_AI_Deployme…...
IGP(Interior Gateway Protocol,内部网关协议)
IGP(Interior Gateway Protocol,内部网关协议) 是一种用于在一个自治系统(AS)内部传递路由信息的路由协议,主要用于在一个组织或机构的内部网络中决定数据包的最佳路径。与用于自治系统之间通信的 EGP&…...
为什么要创建 Vue 实例
核心原因:Vue 需要一个「控制中心」来驱动整个应用 你可以把 Vue 实例想象成你应用的**「大脑」或「引擎」。它负责协调模板、数据、逻辑和行为,将它们变成一个活的、可交互的应用**。没有这个实例,你的代码只是一堆静态的 HTML、JavaScript 变量和函数,无法「活」起来。 …...
【SpringBoot自动化部署】
SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一,能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时,需要添加Git仓库地址和凭证,设置构建触发器(如GitHub…...
基于鸿蒙(HarmonyOS5)的打车小程序
1. 开发环境准备 安装DevEco Studio (鸿蒙官方IDE)配置HarmonyOS SDK申请开发者账号和必要的API密钥 2. 项目结构设计 ├── entry │ ├── src │ │ ├── main │ │ │ ├── ets │ │ │ │ ├── pages │ │ │ │ │ ├── H…...
2.2.2 ASPICE的需求分析
ASPICE的需求分析是汽车软件开发过程中至关重要的一环,它涉及到对需求进行详细分析、验证和确认,以确保软件产品能够满足客户和用户的需求。在ASPICE中,需求分析的关键步骤包括: 需求细化:将从需求收集阶段获得的高层需…...
