FluentValidation如何将Optional类型转换为底层类型并按条件应用校验规则
实现方案
这个需求完全可以实现,核心通过FluentValidation的Transform类型转换能力+规则执行条件控制即可完成,同时可以做成通用泛型扩展方法,支持任意底层类型的Optional<>。
第一步:实现通用扩展方法
using FluentValidation; using System.Linq.Expressions; public static class ValidatorOptionalExtensions { /// <summary> /// 针对Optional类型属性的校验规则构建扩展 /// </summary> /// <typeparam name="TModel">校验模型类型</typeparam> /// <typeparam name="TValue">Optional包裹的底层值类型</typeparam> /// <param name="validator">校验器实例</param> /// <param name="expression">指向Optional属性的表达式</param> /// <returns>针对底层TValue类型的规则构建器</returns> public static IRuleBuilderInitial<TModel, TValue> RuleForOptional<TModel, TValue>( this AbstractValidator<TModel> validator, Expression<Func<TModel, Optional<TValue>>> expression) { // 1. 类型转换:将Optional<TValue>转换为底层TValue,无值时返回对应类型默认值 var rule = validator.Transform(expression, opt => opt.HasValue ? opt.Value : default); // 2. 加执行条件:仅当Optional有值时,才执行后续所有链式校验规则 rule.When(model => expression.Compile().Invoke(model).HasValue); return rule; } }
第二步:使用示例
对应你的场景,调用方式如下:
// 你的模型定义 class Model { public Optional<string> Str { get; set; } } // 校验器实现 class MyValidator : AbstractValidator<Model> { public MyValidator() { // 调用扩展方法构建规则 this.RuleForOptional(x => x.Str) .NotNull() // 此处直接使用string类型的校验规则 .MinimumLength(3) .Matches("^[0-9a-zA-Z]+$"); } }
逻辑说明
- 当
Optional属性的HasValue为false时,When条件不满足,整条规则链会被直接跳过,不会触发任何后续校验 - 当
Optional属性的HasValue为true时,会自动取Value属性的值作为校验对象,应用后续所有针对底层类型的校验规则 - 扩展方法为泛型实现,除了
string之外,Optional<int>、Optional<DateTime>等任意类型都可以直接复用
注意:如果是高并发核心场景,可将表达式的编译结果缓存,避免每次校验都执行编译操作,进一步提升性能。
内容的提问来源于stack exchange,提问作者mihails.kuzmins
相关产品推荐
相关产品推荐

