尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
源码剖析:Blazored.FluentValidation 如何将 FluentValidation 无缝接入 Blazor EditContext
源码剖析Blazored.FluentValidation 如何将 FluentValidation 无缝接入 Blazor EditContext【免费下载链接】FluentValidationA library for using FluentValidation with Blazor项目地址: https://gitcode.com/gh_mirrors/flue/FluentValidationBlazored.FluentValidation 是一个专为 Blazor 打造的 FluentValidation 集成库它用极少的代码将 FluentValidation 的强大校验能力桥接到 Blazor 的 EditContext 验证管道中让EditForm的表单校验变得优雅而自然。本文将从源码层面深入剖析它无缝接入的三大核心机制如何挂钩 EditContext、如何自动发现校验器、以及如何完成字段路径的双向映射帮助你彻底理解这套设计的精妙之处。一、整个库只有 4 个源文件极简架构一览整个核心库位于 src/Blazored.FluentValidation/ 目录下仅 4 个 C# 文件却撑起了完整的功能文件职责FluentValidationsValidator.cs对外暴露的 Blazor 组件作为桥接入口EditContextFluentValidationExtensions.cs核心引擎负责订阅事件、执行校验、映射字段IntersectingCompositeValidatorSelector.cs字段级校验的精妙交集选择器PropertyPathHelper.csFieldIdentifier 与 FluentValidation 属性路径的转换器它只依赖 FluentValidation 和 ASP.NET Core Components 两个包见 Blazored.FluentValidation.csproj支持 net6.0、net7.0、net8.0 三个目标框架零额外依赖的设计让它非常轻量。二、接入第一步如何拿到 EditContext 并挂载自己Blazor 的EditForm组件会通过级联参数CascadingParameter向下传递一个EditContext实例这是整个表单验证的总线。FluentValidationValidator组件继承自ComponentBase正是利用这一机制在 OnInitialized 生命周期中拿到级联的EditContext并立即调用扩展方法完成注册[CascadingParameter] private EditContext? CurrentEditContext { get; set; } protected override void OnInitialized() { CurrentEditContext.AddFluentValidation(ServiceProvider, DisableAssemblyScanning, Validator, this); }这一步非常关键它把 FluentValidation 的校验能力注入到了 Blazor 原生的验证事件流里从此EditContext的每一次验证请求都会自动触发 FluentValidation 校验。三、核心引擎订阅两个事件接管整表与字段校验打开 EditContextFluentValidationExtensions.cs你会发现核心逻辑其实只有两步——创建一个ValidationMessageStore用来存放错误消息然后订阅EditContext的两个事件editContext.OnValidationRequested async (sender, _) await ValidateModel(...); // 整表单验证点击提交时触发 editContext.OnFieldChanged async (_, eventArgs) await ValidateField(...); // 字段级验证输入框内容变化时触发OnValidationRequested表单提交时由EditContext.Validate()触发对应整表全量校验OnFieldChanged任一绑定字段的值变化时触发对应单个字段的实时校验。Blazor 原生组件DataAnnotationsValidator也是同样的模式这说明 Blazored.FluentValidation 完全遵循了 Blazor 的验证扩展点设计这也是它能无缝融入EditForm的根本原因。四、自动发现校验器DI 优先程序集扫描兜底在 ValidateModel 中首先需要找到对应模型的IValidatorT。查找策略在 GetValidatorForModel 中体现得淋漓尽致优先从 DI 容器获取通过typeof(IValidator).MakeGenericType(model.GetType())动态构造泛型类型并解析找不到就扫描程序集遍历当前AppDomain中所有程序集用 FluentValidation 自带的AssemblyScanner.FindValidatorsInAssembly反射查找继承AbstractValidatorT的校验器结果缓存在静态列表中避免重复扫描DisableAssemblyScanning参数如果设置为true则跳过扫描、只信任 DI 注册适合性能敏感或纯 DI 的场景。这种双保险策略让使用者既可以享受 DI 的显式控制参考 samples/BlazorServer/Program.cs也可以享受零配置的自动发现参考 Blazor WebAssembly 示例项目。五、整表校验把 ValidationResult 翻译成 ValidationMessageStore找到校验器后ValidateModel执行一次完整的异步校验然后把结果翻译进 Blazor 的验证系统var asyncValidationTask validator.ValidateAsync(context); editContext.Properties[PendingAsyncValidation] asyncValidationTask; // 挂起任务供异步调用 var validationResults await asyncValidationTask; messages.Clear(); foreach (var validationResult in validationResults.Errors) { var fieldIdentifier ToFieldIdentifier(editContext, validationResult.PropertyName); messages.Add(fieldIdentifier, validationResult.ErrorMessage); } editContext.NotifyValidationStateChanged();这里有两处亮点错误消息准确落位FluentValidation 返回的PropertyName会被转换成FieldIdentifier确保错误提示精准显示在对应输入框下方NotifyValidationStateChanged()通知 Blazor 重新渲染验证 UIValidationMessage、ValidationSummary等原生组件无需任何改动即可展示错误。完整结果还会存入LastValidationResult字典供GetFailuresFromLastValidation方法查询详见 FluentValidationsValidator.cs这样你就能拿到带Severity等完整信息的ValidationFailure实现警告与错误分级展示。六、字段级校验的精妙设计交集选择器只校验变了的字段这是整个库最值得学习的部分。当某个输入框内容变化触发OnFieldChanged时如果直接跑整表校验性能差且会产生其他字段的错误干扰。ValidateField的做法是只校验发生变化的那个字段。具体实现分两步ValidateField用PropertyPathHelper把FieldIdentifier转换为 FluentValidation 的属性路径如Address.Line1构造一个只包含该属性的校验上下文并通过 IntersectingCompositeValidatorSelector.cs 与原有的选择器做交集public bool CanExecute(IValidationRule rule, string propertyPath, IValidationContext context) { return _selectors.All(s s.CanExecute(rule, propertyPath, context)); }这个选择器要求所有子选择器都放行的规则才执行相当于原有规则集 ∩ 当前变更字段从而保证既遵循你配置的 RuleSets / IncludeProperties 策略又只针对当前字段运行校验。最后通过messages.Clear(fieldIdentifier)只清空该字段的旧错误避免闪烁。七、路径双向映射FieldIdentifier 与属性路径互转的秘密Blazor 的FieldIdentifier是(Model实例, 属性名)的二元组而 FluentValidation 的属性路径是字符串支持嵌套如Address.Town、集合索引如Orders[0].Total。库提供了两个方向的转换正向PropertyPathHelper.cs通过栈式深度遍历模型的非原始类型属性重建从根模型到目标字段的完整路径甚至能正确处理集合索引Orders[2]反向ToFieldIdentifier解析类似SomeProp.MyCollection[123].ChildProp的路径逐段用反射走属性、用Item索引器或数组索引访问一路追踪到最深的非空实例。这套映射代码参考了 Steve Sanderson 的经典实现还特别处理了 C# 12 集合表达式生成的IReadOnlyList等边界情况让嵌套模型如 samples/Shared/SharedModels/Person.cs 中 Person 内嵌 Address的校验路径完全一致。八、手动校验与异步校验Validate / ValidateAsync 的背后除了自动接入组件还提供了手动触发入口。Validate()本质上就是调用CurrentEditContext.Validate()走一遍整表校验而ValidateAsync()则更巧妙——它先同步触发校验再从EditContext.Properties中取出上一步挂起的AsyncValidationTask等待完成FluentValidationsValidator.csCurrentEditContext.Validate(); if (!CurrentEditContext.Properties.TryGetValue(PendingAsyncValidation, out var asyncValidationTask)) throw new InvalidOperationException(No pending ValidationResult found); await (TaskValidationResult)asyncValidationTask; return !CurrentEditContext.GetValidationMessages().Any();这样即使校验规则里有MustAsync这类异步方法见 Person.cs 中邮箱唯一性检查也能被完整等待支持 Blazor Server 下的事件处理器安全。九、性能与优雅并存的设计总结回顾整个源码Blazored.FluentValidation 的设计堪称小而美✅零侵入只做事件订阅与消息桥接不改动EditForm的任何行为✅双策略查器DI 优先、反射兜底兼顾性能与便捷✅精准校验交集选择器让字段级验证只跑必要的规则✅边界处理嵌套属性、集合索引、C# 12 集合表达式都有兼容方案。如果你想在自己项目中复刻这种把任意校验框架接入 Blazor 验证管道的能力这份源码就是最好的教科书。测试用例位于 tests/Blazored.FluentValidation.Tests/包含 BasicValidation、DirectValidation、RuleSets、FullFailureAccess 等场景配合阅读效果更佳。无论是想深入理解 Blazor 验证机制还是想学习组件库的优雅设计Blazored.FluentValidation 这 4 个文件都值得你仔细研读一遍 【免费下载链接】FluentValidationA library for using FluentValidation with Blazor项目地址: https://gitcode.com/gh_mirrors/flue/FluentValidation创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
RELATED

相关推荐

SwiftyPickerPopover 按钮定制全解:Done/Cancel/Clear 回调的 10 种玩法

SwiftyPickerPopover 按钮定制全解:Done/Cancel/Clear 回调的 10 种玩法

SwiftyPickerPopover 按钮定制全解:Done/Cancel/Clear 回调的 10 种玩法 【免费下载链接】SwiftyPickerPopover A more convenient way to display a popover with a built-in picker, on iPhone/iPad of iOS9. 项目地址: https://gitcode.com/gh_mirrors/sw/Swif…

📅 2026/10/8 16:13:37
BMW-YOLOv4-Training-Automation Docker 镜像构建完全指南:GPU、CPU、OPENMP 参数详解

BMW-YOLOv4-Training-Automation Docker 镜像构建完全指南:GPU、CPU、OPENMP 参数详解

BMW-YOLOv4-Training-Automation Docker 镜像构建完全指南:GPU、CPU、OPENMP 参数详解 【免费下载链接】BMW-YOLOv4-Training-Automation This repository allows you to get started with training a state-of-the-art Deep Learning model with little to no conf…

📅 2026/9/9 13:34:57
AI大模型qwythos本地部署实战:从零搭建私有化智能引擎

AI大模型qwythos本地部署实战:从零搭建私有化智能引擎

最近,AI大模型领域的一个新名字“qwythos”开始频繁出现在技术社区的讨论中。很多开发者第一眼看到它,可能会被“超强无审查”这样的描述所吸引,但随之而来的是一连串问号:这又是一个昙花一现的“开源明星”,还是真正能…

📅 2026/10/8 1:53:50
MORE NEWS

更多资讯

📰

MariaDB 预处理语句加 CAST 后查询大幅提速的原因

一条带绑定参数的查询,仅仅给参数套上一层看起来毫无必要的 CAST,耗时就从 0.083 秒降到 0.005 秒。在真实数据上是 1.5 秒对 0.3 秒。差别不在 CAST 的计算成本,而在优化器是否愿意把条件下推到视图内部。 问题现象 表与视图定义如下: CREATE DATABASE cast_demoCHARAC…

📰

R 数据框按组内条件动态重置参考日期计算天数差

同一受试者有多条日期记录,需要判断哪些记录属于同一次事件、哪些已经相隔太久应当算作新事件。参考日期默认是组内第一条记录,一旦出现间隔超过阈值的记录,基准就切换到那条记录上。 问题现象 原始数据: dfi <- structure(list(ID = c(1, 1, 2, 2, 2,

📰

BP神经网络在低算力路面裂缝识别中的工程实践

简介&#xff1a;本资源是一篇聚焦工程实践与算法落地的学术论文&#xff0c;面向交通工程、智能检测及人工智能应用领域的高校师生与行业技术人员&#xff0c;旨在解决沥青路面图像噪声强、传统边缘检测易误判裂缝等实际难题。论文提出基于BP神经网络的裂缝识别方法&#xff1…

📰

R 中调用 DuckDB 报 IO Error 无法创建临时目录的排查与修复

在 macOS 上用 R 做地址地理编码时,很多包会组合 duckdb 与 callr:duckdb 负责本地列式计算,callr 负责把重活丢到独立的 R 子进程里跑。这类组合一旦临时目录配置出问题,报错会发生在子进程内部,主会话只能看到一个被包装过的 callr 错误,排查起来很绕。 问题现象 主脚…

📰

IL-6:炎症网络与免疫代谢调控的核心节点分子,信号转导模式与疾病机制全解析

炎症微环境重塑、免疫细胞命运决定与组织损伤修复机制是感染免疫学、肿瘤生物学及代谢性疾病研究的核心方向。白细胞介素- 6&#xff08;Interleukin- 6&#xff0c;IL- 6&#xff09;是机体调控急性期应答、Th17/Treg平衡与肿瘤免疫逃逸的核心多效性细胞因子&#xff0c;也是解…

📰

openSCADA的jar部署与依赖管理:从classpath到模块加载避坑指南

简介&#xff1a;面向Java环境下OpenSCADA二次开发及OPC模块调试的工程师&#xff0c;这套资源将项目启动阶段最繁琐的依赖收集工作一次做完&#xff0c;按OpenSCADA/Java工程实际使用场景归拢全部必需组件。压缩包共480个文件&#xff0c;体积约30.92MB&#xff0c;主体为129个…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬