基于MediatR管道的公共业务校验

news2024/11/26 0:39:48

基于MediatR的管道模式,我们可以在处理业务之前,进行统一验证,记录日志等。

所有命令(Command)再被处理(Handle)之前,都要经过IRequestPreProcessor处理,我们注入自己的拦截器,执行响应的验证代码即可。

下面主要是公司项目的实践,希望能给大家带来启发。

公司项目是 .net core 3.1 web api项目,使用MediatR的命令模式。对于增删改操作,每个接口都有对应的一个Command接收参数,一个Handle类处理命令。一般如果写业务员验证的话,会在Handle类的Handle方法中先去做业务验证,再写执行逻辑。

既然我们统一用了MediatR,那么就可以利用MediatR的管道模式,在处理命令之前,统一执行这些业务验证。

命令与校验器

因为每个业务都有自己独特的业务验证,所有我们为每个命令(command)都创建了对应的校验类(XXXXValidate),当然也有一些公共的校验类。通过注入的方式,将这些校验类注入到命令中。如图中BizBatchSetCreateCommand命令中注入了BizBatchSetCreateValidate校验器。所有需要统一业务校验的命令都必须继承自AutoVerificationCommandBase。校验器需要继承CommandVerificationBase<T>。

 

自定义MediatR拦截器

我司用的MediatR 8.0.0.0,包含接口IRequestPreProcessor<in TRequest>.顾名思义,这是命令被处理前会经过的拦截器。

namespace MediatR.Pipeline
{
    //
    // 摘要:
    //     Defined a request pre-processor for a handler
    //
    // 类型参数:
    //   TRequest:
    //     Request type
    public interface IRequestPreProcessor<in TRequest> where TRequest : notnull
    {
        //
        // 摘要:
        //     Process method executes before calling the Handle method on your handler
        //
        // 参数:
        //   request:
        //     Incoming request
        //
        //   cancellationToken:
        //     Cancellation token
        //
        // 返回结果:
        //     An awaitable task
        Task Process(TRequest request, CancellationToken cancellationToken);
    }
}

我们继承此接口实现通用业务校验类GenericVerificationPreProcessor<TRequest>。Process函数中判断命令(TRequest)是否继承自IAutoVerificationCommand。如果是,取出其中的校验器并逐个执行。

    public class GenericVerificationPreProcessor<TRequest> : IRequestPreProcessor<TRequest>
        where TRequest : class
    {
        IServiceProvider _ServiceProvider;

        /// <summary>
        /// 
        /// </summary>
        public GenericVerificationPreProcessor(IServiceProvider ServiceProvider)
        {
            _ServiceProvider = ServiceProvider;
        }

        /// <summary>
        /// 
        /// </summary>
        public async Task Process(TRequest request, CancellationToken cancellationToken)
        {
            if (request is IAutoVerificationCommand)//继承自动校验接口,表示需要自动校验
            {
                var command = request as IAutoVerificationCommand;
                if (command != null && !command.IsProcessed)
                {
                    command.IsProcessed = true;
                    if (command.VerificationProviders != null)
                    {
                        foreach (var typeOfProvider in command.VerificationProviders)
                        {
                            var service = _ServiceProvider.GetService(typeOfProvider);//通过_ServiceProvider创建校验器
                            if (service == null)
                            {
                                throw new Exception($"无法实例化类型:{typeOfProvider.Name},请检查类型是否已注册.");
                            }

                            if (service is CommandVerificationBase<TRequest>)
                            {
                                var provider = service as CommandVerificationBase<TRequest>;
                                if (provider != null)
                                {
                                    provider.Verify(request);
                                    //Process并没有短路的方法,所以用抛出异常的方式终止当前请求的执行。
                                    provider.RaiseException();
                                }
                            }
                        }
                    }
                }
            }
        }
    }

因为Process不能中断管道的执行,所以当校验不通过的时候,直接抛了异常出来,在我们项目中有全局异常捕获。捕获到异常后会封装错误信息返回,这里就不管了,直接抛出异常了。

拦截器不需要特意的去注册。

当然实现IPipelineBehavior也可以完成上面的功能。逻辑类似。

源码

 

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

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

相关文章

chrome拓展插件开发中使用chrome.storage本地存储

一、描述 在扩展程序中本地存储数据可以通过 chrome.storage API 实现&#xff0c;和 web 中的 localstorage 在某些方面是有区别的&#xff0c;chrome.storage 已经做了优化。 与 localStorage 的区别&#xff1a; 用户数据可以与 chrome 自动同步&#xff08;通过 storage…

【推荐】智能制造工业4.0与MES资料合集

智能制造&#xff0c;源于人工智能的研究&#xff0c;一般认为智能是知识和智力的总和&#xff0c;前者是智能的基础&#xff0c;后者是指获取和运用知识求解的能力。 智能制造应当包含智能制造技术和智能制造系统&#xff0c;智能制造系统不仅能够在实践中不断地充实知识库&a…

请上车MySQL面试必备点:从常见的存储引擎到混淆的锁分类

我们之前的文章InnoDB解决幻读的方案中提到了记录锁&#xff08;行锁&#xff09;、间隙锁和临键锁&#xff0c;后台有小伙伴催我更新一下其他的锁。拖延症又犯了&#xff0c;趁周末&#xff0c;今天我们来总结一下MyISAM和InnoDB引擎下锁的种类及使用方法。 MySQL的四大常见存…

面试题:Linux是如何避免内存碎片的

Linux是如何避免内存碎片的&#xff1f; 在网上看到这个面试题&#xff0c;参考答案是这样的&#xff1a; 伙伴算法&#xff0c;用于管理物理内存&#xff0c;避免内存碎片;高速缓存Slab层用于管理内核分配内存&#xff0c;避免碎片。 故继而去深入了解了一波&#xff0c;做了…

牛客之基础单片机知识_1

✅作者简介&#xff1a;大家好我是 xxx&#xff0c;是一名嵌入式工程师&#xff0c;希望一起努力&#xff0c;一起进步&#xff01; &#x1f4c3;参照主页&#xff1a;嵌入式基地 &#x1f525;系列专栏&#xff1a;硬件基础知识——单片机 习题专栏 &#x1f4ac;网上关于嵌入…

软件测试不常用但是一定要会的测试技术与用例设计

一、认识基本术语 术语一&#xff1a; ◆动态测试&#xff08;dynamic testing&#xff09; 通过运行软件的组件或系统来测试软件(实际运行被测软件/系统)【需要进行操作】 ◆静态测试&#xff08;static testing) 对组件的规格说明书进行评审&#xff0c;对静态代码进行走…

【推荐】700套高端简历模板合集

简历&#xff08;英语&#xff1a;resume&#xff09;&#xff0c;顾名思义&#xff0c;就是对个人学历、经历、特长、爱好及其它有关情况所作的简明扼要的书面介绍。简历是有针对性的自我介绍的一种规范化、逻辑化的书面表达。对应聘者来说&#xff0c;简历是求职的“敲门砖”…

JSP学生宿舍网站

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 模块划分&#xff1a;通知类型模块、通知信息模块、院系信息、班级信息、宿舍 楼信息、宿舍信息、宿管信息、学生信息、…

three.js之多线条组合

文章目录多线条组合例子专栏目录请点击 多线条组合 我们可以通过CurvePath把多个曲线、直线等合并成一个曲线 例子 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><style>body {margin: 0;overflow: hidde…

CSS习题解答

文章目录1.1 样式定义方式1.2 选择器1.3 颜色1.4 文本1.5 字体1.6 背景1.7 边框1.8 元素展示格式1.9 内边距与外边距1.10 盒子模型1.11 位置1.12 浮动实战&#xff1a;个人名片1.13 flex布局1.14 响应式布局作业01作业02作业03作业04作业05作业06作业07作业08作业09作业10其他1…

正则表达式学习

文章目录入门开始和结束字符组区间特殊字符转义取反快捷匹配数字和字母匹配空白任意字符重复次数和区间或者条件进阶分组非捕获分组分组的引用正向先行断言反向先行断言正向后行断言反向后行断言常用元字符整理相关网站在线测试网站题目练习网站其他笔记入门 开始和结束 正则…

计算机毕设Python+Vue学生量化考核系统(程序+LW+部署)

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Python中groupby函数详解(非常容易懂)

目录&#xff1a;Python中的groupby函数一、groupby 能做什么&#xff1f;二、单类分组2.1 创建数据集三、多类分组一、groupby 能做什么&#xff1f; groupby函数主要的作用是进行数据的分组以及分组后地组内运算&#xff01; 于数据的分组和分组运算主要是指groupby函数的应…

网络安全等级保护十问十答

网络安全等级保护十问十答1.什么是等级保护&#xff1f;2.为什么需要等级保护&#xff1f;3.目标客户是&#xff1f;4.等保工作步骤包括什么&#xff1f;5.等保测评结论有几种结果&#xff1f;6.等保如何定级&#xff1f;7. 定级对象在哪备案&#xff1f;8. 等级保护都测评什么…

[附源码]计算机毕业设计Node.js宠物商店网站(程序+LW)

项目运行 环境配置&#xff1a; Node.js最新版 Vscode Mysql5.7 HBuilderXNavicat11Vue。 项目技术&#xff1a; Express框架 Node.js Vue 等等组成&#xff0c;B/S模式 Vscode管理前后端分离等等。 环境需要 1.运行环境&#xff1a;最好是Nodejs最新版&#xff0c;我…

Opencv(C++)笔记--Sobel算子

1--Sobel算子 1-1--原理 Sobel算子的构成如下图所示&#xff1a; 基于 Sobel 算子可以实现对图像的边缘检测&#xff0c;Gx常用于提取纵向边缘&#xff0c;Gy则常用于提取横向边缘&#xff1b; 1-2--Opencv API 在 ddeth 参数上&#xff0c;使用 cv::CV_16S 处理 8 位原图像&…

jsp+ssm计算机毕业设计高校班主任班级管理系统【附源码】

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; JSPSSM mybatis Maven等等组成&#xff0c;B/S模式 Mave…

跨模态检索的简单实现(pytorch)

目录说明说明往期文章和专栏代码及数据集下载什么是跨模态检索代码导入需要的库构建图像、文本子网络加载数据集计算mAP损失函数构建总损失函数训练部分主函数参数设置查看结果说明 说明 还是读研时候剩下的代码&#xff0c;是我从几篇论文里面摘出来的代码做了简单的拼装&am…

SCN时间序列预测模型详解(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 SCN&#xff08;System Change Number 简称 SCN&#xff09;是当Oracle数据库更新后&#xff0c;由DBMS自动维护去累积递增的一…

数据结构链式栈

上一节我们学习了顺序栈 我们了解到栈就是特殊的线性表 我们之前用过顺序表实现了栈 那么我们也可以用单链表的方式来实现一个链式栈 我们可以回顾一下单链表的结构 基础数据结构链表_iccoke的博客-CSDN博客 我们可以看到简单的对尾部进行操作 很难实现时间复杂度达到O&am…