后端【免费下载链接】FluentValidationA popular .NET validation library for building strongly-typed validation rules.项目地址https://gitcode.com/gh_mirrors/fl/FluentValidation点击查看免费下载导读本文基于 FluentValidation 官方入门文档docs/start.md带你从零创建一个强类型验证器先通过AbstractValidatorT与RuleFor定义规则再调用Validate获取ValidationResult处理错误随后深入链式验证、ValidateAndThrow异常抛出以及通过SetValidator复用子验证器验证复杂属性。文末结合当前仓库的 AbstractValidator.cs、ValidationResult.cs、ValidationStrategy.cs 等源码揭示每一步背后的底层实现原理帮助你在实际项目中写出严谨、可维护的验证逻辑。创建你的第一个验证器FluentValidation 采用验证器Validator与业务对象分离的设计要为某个对象定义一组验证规则你需要创建一个继承自AbstractValidatorT的类其中T就是要验证的对象类型。假设你有一个Customer类public class Customer { public int Id { get; set; } public string Surname { get; set; } public string Forename { get; set; } public decimal Discount { get; set; } public string Address { get; set; } }通过继承AbstractValidatorCustomer来定义它的验证器using FluentValidation; public class CustomerValidator : AbstractValidatorCustomer { }验证规则本身应当写在验证器类的构造函数中。构造函数会在验证器实例化时执行通过流式 API 把一条条规则注册到内部规则集合里。要针对某个属性指定验证规则调用RuleFor方法并传入一个指示待验证属性的 lambda 表达式。例如要确保Surname不为 null验证器写成using FluentValidation; public class CustomerValidator : AbstractValidatorCustomer { public CustomerValidator() { RuleFor(customer customer.Surname).NotNull(); } }从源码看RuleFor的定义位于 AbstractValidator.cs它把 lambda 表达式交给PropertyRuleT, TProperty.Create解析成一条内部规则添加到Rules集合并返回一个RuleBuilder供后续链式调用。也就是说构造函数中每写一条RuleFor就相当于向验证器注册了一条待执行规则验证器还实现了IEnumerableIValidationRule因此可以直接遍历它持有的全部规则。运行验证Validate 方法与 ValidationResult定义好验证器后实例化它并调用Validate方法传入要验证的对象即可执行验证Customer customer new Customer(); CustomerValidator validator new CustomerValidator(); ValidationResult result validator.Validate(customer);Validate返回一个ValidationResult对象其中包含两个核心属性IsValid—— 布尔值表示验证是否成功。Errors—— 一组ValidationFailure对象包含所有验证失败的详细信息。IsValid的实现非常直观见 ValidationResult.csErrors.Count 0即验证成功。Errors集合中的每个ValidationFailure都携带丰富信息除PropertyName属性名与ErrorMessage错误消息外还包含AttemptedValue导致失败的值、CustomState自定义状态、Severity严重级别默认Severity.Error与ErrorCode错误码完整定义见 ValidationFailure.cs。下面的代码会把所有验证失败信息输出到控制台using FluentValidation.Results; Customer customer new Customer(); CustomerValidator validator new CustomerValidator(); ValidationResult results validator.Validate(customer); if(! results.IsValid) { foreach(var failure in results.Errors) { Console.WriteLine(Property failure.PropertyName failed validation. Error was: failure.ErrorMessage); } }将错误合并为字符串ToStringValidationResult还重写了ToString可以把所有错误消息合并成单个字符串。默认使用换行符分隔各条消息如果你想自定义分隔符可以向ToString传入一个分隔字符ValidationResult results validator.Validate(customer); string allMessages results.ToString(~); // In this case, each message will be separated with a ~源码层面ToString()无参重载委托给ToString(Environment.NewLine)最终通过string.Join(separator, _errors.Select(failure failure.ErrorMessage))拼接见 ValidationResult.cs。注意如果没有验证错误ToString()会返回一个空字符串。另外ValidationResult还提供ToDictionary()方法将错误按属性名分组返回IDictionarystring, string[]便于在 API 层直接序列化或绑定到表单错误上。链式验证一条规则串联多个约束你可以针对同一个属性把多个验证器链在一起每个验证器按书写顺序依次执行using FluentValidation; public class CustomerValidator : AbstractValidatorCustomer { public CustomerValidator() { RuleFor(customer customer.Surname).NotNull().NotEqual(foo); } }这条链式规则同时确保Surname不为 null且不等于字符串foo。链式调用的机制在于RuleFor返回的IRuleBuilder上挂载了一系列内置验证器扩展方法.NotNull()、.NotEqual()、.Length()、.EmailAddress()等每个方法都会把一个新的验证器组件追加到当前规则上并返回构建器本身以继续链式调用。仓库中的内置验证器分布在 src/FluentValidation/Validators 目录下例如 NotNullValidator.cs、EqualValidator.cs。需要说明的是链式验证属于**规则内部rule-level**的级联行为默认情况下同一条链上的验证器无论前一个是否失败都会全部执行若希望同一条链上某个验证器失败后立即停止后续验证器可通过级联模式CascadeMode配置相关机制详见 cascade.md。抛出异常ValidateAndThrow前面使用Validate时验证失败只会体现在返回的ValidationResult中并不会中断程序。如果你希望在验证失败时直接抛出异常可以使用ValidateAndThrow方法Customer customer new Customer(); CustomerValidator validator new CustomerValidator(); validator.ValidateAndThrow(customer);当验证失败时它会抛出一个ValidationException该异常通过Errors属性携带全部错误消息异常类型定义见 ValidationException.cs其Errors为IEnumerableValidationFailure。注意ValidateAndThrow是一个扩展方法因此文件顶部必须用using FluentValidation;引入命名空间该方法才可用。同步版本ValidateAndThrow与异步版本ValidateAndThrowAsync都定义在 DefaultValidatorExtensions_Validate.cs 中。底层等价写法Options APIValidateAndThrow本质上是 FluentValidation Options API 的一个便捷封装等价于validator.Validate(customer, options options.ThrowOnFailures());ThrowOnFailures()定义于 ValidationStrategy.cs它会设置内部_throw标志使得Validate执行完毕后若结果无效便抛出异常。如果需要在抛异常的同时组合使用 Rule Sets规则集或只验证指定属性可以通过 Options 语法同时配置多个选项validator.Validate(customer, options { options.ThrowOnFailures(); options.IncludeRuleSets(MyRuleSets); options.IncludeProperties(x x.Name); });这里用到的三个关键方法都来自ValidationStrategyTThrowOnFailures()验证失败时抛异常IncludeRuleSets(MyRuleSets)仅执行指定规则集中的规则IncludeProperties(x x.Name)仅验证指定属性。ValidationStrategy还提供IncludeAllRuleSets()相当于*执行所有规则、IncludeRulesNotInRuleSet()相当于default只执行不在规则集中的规则和UseCustomSelector(...)使用自定义选择器等高级选项。当多个选项同时出现时内部会将对应的MemberNameValidatorSelector、RulesetValidatorSelector组合成CompositeValidatorSelector一起生效。仓库中的测试 ValidateAndThrowTester.cs 验证了相关行为验证失败时抛出ValidationException、携带错误信息、验证成功时不抛出异常以及规则集与ValidateAndThrowAsync的组合场景。自定义异常类型ValidateAndThrow默认抛出ValidationException。如果需要每次抛出特定类型的自定义异常可以通过在验证器中重写RaiseValidationException方法实现具体做法见 自定义验证异常。复杂属性复用子验证器验证器可以针对复杂属性进行复用。假设有两个类Customer和Addresspublic class Customer { public string Name { get; set; } public Address Address { get; set; } } public class Address { public string Line1 { get; set; } public string Line2 { get; set; } public string Town { get; set; } public string Country { get; set; } public string Postcode { get; set; } }先为Address定义一个AddressValidatorpublic class AddressValidator : AbstractValidatorAddress { public AddressValidator() { RuleFor(address address.Postcode).NotNull(); //etc } }然后在CustomerValidator中通过SetValidator复用它public class CustomerValidator : AbstractValidatorCustomer { public CustomerValidator() { RuleFor(customer customer.Name).NotNull(); RuleFor(customer customer.Address).SetValidator(new AddressValidator()); } }这样当调用CustomerValidator的Validate时会依次执行CustomerValidator与AddressValidator中定义的所有规则并把两部分的失败信息合并到同一个ValidationResult中返回。子属性为 null 时的行为如果子属性为 null则子验证器不会执行。这一行为在源码 ChildValidatorAdaptor.cs 中清晰可见IsValid方法第一步就是if (value null) return true;即属性值为 null 时直接跳过子验证器。RuleBuilder.SetValidator(IValidatorTProperty)见 RuleBuilder.cs内部会把这个子验证器包装成ChildValidatorAdaptor并注册到规则中同时它天然支持同步与异步执行。替代方案内联子规则除了使用子验证器你也可以直接内联定义子属性规则RuleFor(customer customer.Address.Postcode).NotNull()注意这种写法不会自动对Address执行 null 检查——属性表达式直接穿透到了Address.Postcode。如果Address为 null访问Postcode会引发空引用问题因此需要显式添加条件RuleFor(customer customer.Address.Postcode).NotNull().When(customer customer.Address ! null).When(...)接收一个谓词只有谓词返回 true 时才执行该规则Address不为 null 时才校验Postcode。与之对应的否定形式是.Unless(...)谓词为 false 时执行。两者的实现同样位于 AbstractValidator.cs 中。延伸从源码看验证执行链路Validate 的完整流程AbstractValidator.cs 中Validate(T instance)会构造一个ValidationContextT然后进入ValidateInternal先调用PreValidate钩子再遍历Rules集合逐条执行当某条规则产生失败且验证器的ClassLevelCascadeMode CascadeMode.Stop时会提前终止后续规则快速失败。此外传入 null 模型会抛出InvalidOperationException提示根模型不能为 null。同步遍历规则时若遇到异步验证器会抛出AsyncValidatorInvokedSynchronouslyException提醒开发者改用ValidateAsync。异步验证对于包含MustAsync、SetValidator等异步验证器的场景应使用ValidateAsync见 AbstractValidator.cs它接受一个CancellationToken并会逐条执行规则的异步版本ValidationResult result await validator.ValidateAsync(customer, cancellationToken);注意ValidateAsync与Validate是两条独立的执行路径同步调用无法执行异步规则反之亦然请根据实际规则类型选择对应入口。级联模式CascadeModeAbstractValidatorT暴露了ClassLevelCascadeMode规则之间与RuleLevelCascadeMode单条规则内部两个可配置属性默认值分别取自ValidatorOptions.Global.DefaultClassLevelCascadeMode与DefaultRuleLevelCascadeMode见 AbstractValidator.cs。Continue表示无论是否失败都继续执行Stop表示失败即停止这是控制失败后短路行为的关键开关详见 cascade.md。小结通过本文你已经掌握了 FluentValidation 的完整入门链路用AbstractValidatorT定义验证器在构造函数中用RuleFor lambda 声明属性规则调用Validate得到ValidationResult通过IsValid/Errors检查结果用ToString/ToDictionary汇总错误用链式调用对同一属性叠加多个约束用ValidateAndThrow及其 Options API 等价形式在失败时抛出ValidationException用SetValidator复用子验证器验证复杂属性并注意子属性为 null 时的自动跳过与内联规则下需要手动添加When条件。以上示例代码均可直接复制运行。若要继续深入可依次阅读仓库中的 custom-validators.md、built-in-validators.md、collections.md 与 testing.md 等文档。赞分享后端【免费下载链接】FluentValidationA popular .NET validation library for building strongly-typed validation rules.项目地址https://gitcode.com/gh_mirrors/fl/FluentValidation点击查看免费下载相关推荐FluentValidation入门指南创建第一个验证器FluentValidation入门指南创建第一个验证器 什么是FluentValidation FluentValidation是一个流行的.NET验证库后端搞定复杂数据验证FluentValidation对象与集合校验实战搞定复杂数据验证FluentValidation对象与集合校验实战 你还在为嵌套表单数据校验抓狂用户提交的订单列表总是包含无效商品本文将带你掌握Fluen后端快速上手FluentValidation从零构建你的第一个验证器的完整教程快速上手FluentValidation从零构建你的第一个验证器的完整教程 FluentValidation 是一款广受欢迎的 .NET 验证库它通过流式接后端上一篇Fedora-Hyprland性能优化技巧让你的Hyprland桌面运行如飞下一篇Ytt 集成开发指南如何将模板引擎嵌入你的 Go 应用创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
