😊 改进 新数据验证模块的条件验证器功能

This commit is contained in:
MonkSoul
2025-12-01 16:57:28 +08:00
parent abbb8f4af0
commit 62f1dc8bb0
10 changed files with 280 additions and 310 deletions

View File

@@ -25,21 +25,27 @@
namespace Furion.Validation;
/// <summary>
/// 链式条件构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public class FluentConditionBuilder<T> : FluentValidatorBuilder<T, FluentConditionBuilder<T>>;
/// <summary>
/// 条件构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public sealed class ConditionBuilder<T>
public class ConditionBuilder<T>
{
/// <summary>
/// 条件和对应的验证器列表
/// </summary>
internal readonly List<(Func<T, bool> Condition, ValidatorBase Validator)> _conditions;
internal readonly List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> _conditions;
/// <summary>
/// 缺省验证器
/// 缺省验证器集合
/// </summary>
internal ValidatorBase? _defaultValidator;
internal IReadOnlyList<ValidatorBase>? _defaultValidators;
/// <summary>
/// <inheritdoc cref="ConditionBuilder{T}" />
@@ -47,159 +53,92 @@ public sealed class ConditionBuilder<T>
internal ConditionBuilder() => _conditions = [];
/// <summary>
/// 添加条件和对应的验证器
/// 添加条件和对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> AddCondition(Func<T, bool> condition, ValidatorBase validator)
public ConditionBuilder<T> AddCondition(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
ArgumentNullException.ThrowIfNull(validator);
_conditions.Add((condition, validator));
_conditions.Add((condition, BuildValidators(configure)));
return this;
}
/// <summary>
/// 添加条件成立时对应的验证器
/// 添加条件成立时对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> When(Func<T, bool> condition, ValidatorBase validator) =>
AddCondition(condition, validator);
public ConditionBuilder<T> When(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure) =>
AddCondition(condition, configure);
/// <summary>
/// 添加条件不成立时对应的验证器
/// 添加条件不成立时对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Unless(Func<T, bool> condition, ValidatorBase validator)
public ConditionBuilder<T> Unless(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
return AddCondition(u => !condition(u), validator);
return AddCondition(u => !condition(u), configure);
}
/// <summary>
/// 设置默认验证器
/// 设置默认验证器集合
/// </summary>
/// <remarks>当没有条件匹配时使用。</remarks>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Otherwise(ValidatorBase validator)
public ConditionBuilder<T> Otherwise(Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(validator);
_defaultValidator = validator;
_defaultValidators = BuildValidators(configure);
return this;
}
/// <summary>
/// 添加条件成立时对应的错误消息
/// 构建验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// <see cref="IReadOnlyList{T}" />
/// </returns>
public ConditionBuilder<T> Must(Func<T, bool> condition, string? errorMessage = null)
internal static IReadOnlyList<ValidatorBase> BuildValidators(Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
ArgumentNullException.ThrowIfNull(configure);
// 初始化 MustValidator<T> 验证器
var validator = new MustValidator<T>(condition);
// 初始化 FluentConditionBuilder<T> 实例
var fluentConditionBuilder = new FluentConditionBuilder<T>();
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
// 调用自定义配置委托
configure.Invoke(fluentConditionBuilder);
return AddCondition(condition, validator);
return fluentConditionBuilder.Build();
}
/// <summary>
/// 添加条件不成立时对应的错误消息
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> MustUnless(Func<T, bool> condition, string? errorMessage = null)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
// 初始化 MustUnlessValidator<T> 验证器
var validator = new MustUnlessValidator<T>(condition);
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
return AddCondition(condition, validator);
}
/// <summary>
/// 添加条件成立时对应的错误消息
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Predicate(Func<T, bool> condition, string? errorMessage = null)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
// 初始化 PredicateValidator<T> 验证器
var validator = new PredicateValidator<T>(condition);
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
return AddCondition(condition, validator);
}
/// <summary>
/// 构建条件和默认验证器
/// 构建条件和默认验证器集合
/// </summary>
/// <returns>
/// <see cref="Tuple{T1,T2}" />
/// </returns>
internal (List<(Func<T, bool> Condition, ValidatorBase Validator)> Conditions, ValidatorBase? DefaultValidator)
Build() =>
(_conditions, _defaultValidator);
internal (List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> Conditions,
IReadOnlyList<ValidatorBase>? DefaultValidators) Build() => (_conditions, _defaultValidators);
}

View File

@@ -30,12 +30,12 @@ using System.Globalization;
namespace Furion.Validation;
/// <summary>
/// 链式验证器抽象基类
/// 链式验证器构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <typeparam name="TSelf">派生类型自身类型</typeparam>
public abstract class FluentValidatorBase<T, TSelf>
where TSelf : FluentValidatorBase<T, TSelf>
public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
: FluentValidatorBuilder<T, TSelf>
{
/// <inheritdoc cref="IServiceProvider" />
internal readonly IServiceProvider? _serviceProvider;
@@ -56,12 +56,12 @@ public abstract class FluentValidatorBase<T, TSelf>
internal ValidatorBase? _lastAddedValidator;
/// <summary>
/// <inheritdoc cref="FluentValidatorBase{T,TSelf}" />
/// <inheritdoc cref="FluentValidatorBuilder{T,TSelf}" />
/// </summary>
/// <param name="serviceProvider">
/// <see cref="IServiceProvider" />
/// </param>
internal FluentValidatorBase(IServiceProvider? serviceProvider = null)
internal FluentValidatorBuilder(IServiceProvider? serviceProvider = null)
{
_serviceProvider = serviceProvider;
Validators = [];
@@ -72,16 +72,19 @@ public abstract class FluentValidatorBase<T, TSelf>
/// </summary>
internal TSelf This => (TSelf)this;
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证器集合
/// </summary>
internal List<ValidatorBase> Validators { get; }
/// <summary>
/// 获取验证器集合
/// </summary>
/// <returns>
/// <see cref="IReadOnlyList{T}" />
/// </returns>
public IReadOnlyList<ValidatorBase> GetValidators() => Validators;
/// <summary>
/// 批量添加添加验证器
/// </summary>
@@ -206,20 +209,6 @@ public abstract class FluentValidatorBase<T, TSelf>
return This;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <typeparamref name="TSelf" />
/// </returns>
public TSelf WithDisplayName(string? displayName)
{
DisplayName = displayName;
return This;
}
/// <summary>
/// 添加年龄0-120 岁)验证器
/// </summary>
@@ -834,4 +823,12 @@ public abstract class FluentValidatorBase<T, TSelf>
/// </returns>
public TSelf AddAnnotations(ValidationAttribute[] attributes, IDictionary<object, object?>? items) =>
AddValidator(new ValueAnnotationValidator(attributes, _serviceProvider, items));
/// <summary>
/// 构建验证器集合
/// </summary>
/// <returns>
/// <see cref="IReadOnlyList{T}" />
/// </returns>
internal IReadOnlyList<ValidatorBase> Build() => Validators;
}

View File

@@ -33,8 +33,8 @@ namespace Furion.Validation;
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <typeparam name="TProperty">属性类型</typeparam>
public sealed partial class PropertyValidator<T, TProperty> :
FluentValidatorBase<TProperty, PropertyValidator<T, TProperty>>,
public sealed partial class
PropertyValidator<T, TProperty> : FluentValidatorBuilder<TProperty, PropertyValidator<T, TProperty>>,
IObjectValidator<T>
where T : class
{
@@ -81,6 +81,11 @@ public sealed partial class PropertyValidator<T, TProperty> :
/// </remarks>
internal bool? SuppressAnnotationValidation { get; private set; }
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证条件
/// </summary>
@@ -288,6 +293,20 @@ public sealed partial class PropertyValidator<T, TProperty> :
return this;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <see cref="PropertyValidator{T,TProperty}" />
/// </returns>
public PropertyValidator<T, TProperty> WithDisplayName(string? displayName)
{
DisplayName = displayName;
return this;
}
/// <summary>
/// 检查是否应该对该属性执行验证
/// </summary>

View File

@@ -31,7 +31,7 @@ namespace Furion.Validation;
/// 单个值验证器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
public class ValueValidator<T> : FluentValidatorBuilder<T, ValueValidator<T>>
{
/// <summary>
/// <inheritdoc cref="ValueValidator{T}" />
@@ -44,6 +44,11 @@ public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
{
}
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证条件
/// </summary>
@@ -145,6 +150,20 @@ public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
return this;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <see cref="ValueValidator{T}" />
/// </returns>
public ValueValidator<T> WithDisplayName(string? displayName)
{
DisplayName = displayName;
return this;
}
/// <summary>
/// 检查是否应该对该对象执行验证
/// </summary>

View File

@@ -36,12 +36,12 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <summary>
/// 条件和对应的验证器列表
/// </summary>
internal readonly List<(Func<T, bool> Condition, ValidatorBase Validator)> _conditions;
internal readonly List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> _conditions;
/// <summary>
/// 缺省验证器
/// 缺省验证器集合
/// </summary>
internal readonly ValidatorBase? _defaultValidator;
internal IReadOnlyList<ValidatorBase>? _defaultValidators;
/// <summary>
/// <inheritdoc cref="ConditionalValidator{T}" />
@@ -58,8 +58,8 @@ public class ConditionalValidator<T> : ValidatorBase<T>
// 调用条件构建器配置委托
buildConditions(conditionBuilder);
// 构建条件和默认验证器
(_conditions, _defaultValidator) = conditionBuilder.Build();
// 构建条件和默认验证器集合
(_conditions, _defaultValidators) = conditionBuilder.Build();
ErrorMessageResourceAccessor = () => null!;
}
@@ -67,44 +67,45 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <inheritdoc />
public override bool IsValid(T? instance)
{
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
if (condition(instance!))
{
return validator.IsValid(instance);
return validators.All(u => u.IsValid(instance));
}
}
// 没有匹配条件时使用默认验证器
return _defaultValidator is null || _defaultValidator.IsValid(instance);
// 没有匹配条件时使用默认验证器集合
return _defaultValidators is null || _defaultValidators.All(u => u.IsValid(instance));
}
/// <inheritdoc />
public override List<ValidationResult>? GetValidationResults(T? instance, string name)
{
// 初始化匹配到的验证器
ValidatorBase? matchedValidator = null;
// 初始化匹配到的验证器集合
IReadOnlyList<ValidatorBase>? matchedValidators = null;
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
// ReSharper disable once InvertIf
if (condition(instance!))
{
matchedValidator = validator;
matchedValidators = validators;
break;
}
}
// 没有匹配条件时使用默认验证器
matchedValidator ??= _defaultValidator;
// 没有匹配条件时使用默认验证器集合
matchedValidators ??= _defaultValidators;
// 获取验证结果集合
var validationResults = matchedValidator?.GetValidationResults(instance, name) ?? [];
var validationResults =
matchedValidators?.SelectMany(u => u.GetValidationResults(instance, name) ?? []).ToList();
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
if (validationResults?.Count > 0 && (string?)ErrorMessageString is not null)
{
validationResults.Insert(0, new ValidationResult(FormatErrorMessage(name), [name]));
}
@@ -115,27 +116,37 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <inheritdoc />
public override void Validate(T? instance, string name)
{
// 初始化匹配到的验证器
ValidatorBase? matchedValidator = null;
// 初始化匹配到的验证器集合
IReadOnlyList<ValidatorBase>? matchedValidators = null;
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
// ReSharper disable once InvertIf
if (condition(instance!))
{
matchedValidator = validator;
matchedValidators = validators;
break;
}
}
// 没有匹配条件时使用默认验证器
matchedValidator ??= _defaultValidator;
// 没有匹配条件时使用默认验证器集合
matchedValidators ??= _defaultValidators;
// 空检查
if (matchedValidator is not null && !matchedValidator.IsValid(instance))
if (matchedValidators is null)
{
ThrowValidationException(instance, name, matchedValidator);
return;
}
// 遍历验证器集合
foreach (var validator in matchedValidators)
{
// 检查对象合法性
if (!validator.IsValid(instance))
{
ThrowValidationException(instance, name, validator);
}
}
}

View File

@@ -25,21 +25,27 @@
namespace Furion.Validation;
/// <summary>
/// 链式条件构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public class FluentConditionBuilder<T> : FluentValidatorBuilder<T, FluentConditionBuilder<T>>;
/// <summary>
/// 条件构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public sealed class ConditionBuilder<T>
public class ConditionBuilder<T>
{
/// <summary>
/// 条件和对应的验证器列表
/// </summary>
internal readonly List<(Func<T, bool> Condition, ValidatorBase Validator)> _conditions;
internal readonly List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> _conditions;
/// <summary>
/// 缺省验证器
/// 缺省验证器集合
/// </summary>
internal ValidatorBase? _defaultValidator;
internal IReadOnlyList<ValidatorBase>? _defaultValidators;
/// <summary>
/// <inheritdoc cref="ConditionBuilder{T}" />
@@ -47,159 +53,92 @@ public sealed class ConditionBuilder<T>
internal ConditionBuilder() => _conditions = [];
/// <summary>
/// 添加条件和对应的验证器
/// 添加条件和对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> AddCondition(Func<T, bool> condition, ValidatorBase validator)
public ConditionBuilder<T> AddCondition(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
ArgumentNullException.ThrowIfNull(validator);
_conditions.Add((condition, validator));
_conditions.Add((condition, BuildValidators(configure)));
return this;
}
/// <summary>
/// 添加条件成立时对应的验证器
/// 添加条件成立时对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> When(Func<T, bool> condition, ValidatorBase validator) =>
AddCondition(condition, validator);
public ConditionBuilder<T> When(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure) =>
AddCondition(condition, configure);
/// <summary>
/// 添加条件不成立时对应的验证器
/// 添加条件不成立时对应的验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Unless(Func<T, bool> condition, ValidatorBase validator)
public ConditionBuilder<T> Unless(Func<T, bool> condition, Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
return AddCondition(u => !condition(u), validator);
return AddCondition(u => !condition(u), configure);
}
/// <summary>
/// 设置默认验证器
/// 设置默认验证器集合
/// </summary>
/// <remarks>当没有条件匹配时使用。</remarks>
/// <param name="validator">
/// <see cref="ValidatorBase" />
/// </param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Otherwise(ValidatorBase validator)
public ConditionBuilder<T> Otherwise(Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(validator);
_defaultValidator = validator;
_defaultValidators = BuildValidators(configure);
return this;
}
/// <summary>
/// 添加条件成立时对应的错误消息
/// 构建验证器集合
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <param name="configure">自定义配置委托</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// <see cref="IReadOnlyList{T}" />
/// </returns>
public ConditionBuilder<T> Must(Func<T, bool> condition, string? errorMessage = null)
internal static IReadOnlyList<ValidatorBase> BuildValidators(Action<FluentConditionBuilder<T>> configure)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
ArgumentNullException.ThrowIfNull(configure);
// 初始化 MustValidator<T> 验证器
var validator = new MustValidator<T>(condition);
// 初始化 FluentConditionBuilder<T> 实例
var fluentConditionBuilder = new FluentConditionBuilder<T>();
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
// 调用自定义配置委托
configure.Invoke(fluentConditionBuilder);
return AddCondition(condition, validator);
return fluentConditionBuilder.Build();
}
/// <summary>
/// 添加条件不成立时对应的错误消息
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> MustUnless(Func<T, bool> condition, string? errorMessage = null)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
// 初始化 MustUnlessValidator<T> 验证器
var validator = new MustUnlessValidator<T>(condition);
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
return AddCondition(condition, validator);
}
/// <summary>
/// 添加条件成立时对应的错误消息
/// </summary>
/// <param name="condition">条件委托</param>
/// <param name="errorMessage">错误信息</param>
/// <returns>
/// <see cref="ConditionBuilder{T}" />
/// </returns>
public ConditionBuilder<T> Predicate(Func<T, bool> condition, string? errorMessage = null)
{
// 空检查
ArgumentNullException.ThrowIfNull(condition);
// 初始化 PredicateValidator<T> 验证器
var validator = new PredicateValidator<T>(condition);
// 空检查
if (errorMessage is not null)
{
validator.WithErrorMessage(errorMessage);
}
return AddCondition(condition, validator);
}
/// <summary>
/// 构建条件和默认验证器
/// 构建条件和默认验证器集合
/// </summary>
/// <returns>
/// <see cref="Tuple{T1,T2}" />
/// </returns>
internal (List<(Func<T, bool> Condition, ValidatorBase Validator)> Conditions, ValidatorBase? DefaultValidator)
Build() =>
(_conditions, _defaultValidator);
internal (List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> Conditions,
IReadOnlyList<ValidatorBase>? DefaultValidators) Build() => (_conditions, _defaultValidators);
}

View File

@@ -30,12 +30,12 @@ using System.Globalization;
namespace Furion.Validation;
/// <summary>
/// 链式验证器抽象基类
/// 链式验证器构建器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <typeparam name="TSelf">派生类型自身类型</typeparam>
public abstract class FluentValidatorBase<T, TSelf>
where TSelf : FluentValidatorBase<T, TSelf>
public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
: FluentValidatorBuilder<T, TSelf>
{
/// <inheritdoc cref="IServiceProvider" />
internal readonly IServiceProvider? _serviceProvider;
@@ -56,12 +56,12 @@ public abstract class FluentValidatorBase<T, TSelf>
internal ValidatorBase? _lastAddedValidator;
/// <summary>
/// <inheritdoc cref="FluentValidatorBase{T,TSelf}" />
/// <inheritdoc cref="FluentValidatorBuilder{T,TSelf}" />
/// </summary>
/// <param name="serviceProvider">
/// <see cref="IServiceProvider" />
/// </param>
internal FluentValidatorBase(IServiceProvider? serviceProvider = null)
internal FluentValidatorBuilder(IServiceProvider? serviceProvider = null)
{
_serviceProvider = serviceProvider;
Validators = [];
@@ -72,16 +72,19 @@ public abstract class FluentValidatorBase<T, TSelf>
/// </summary>
internal TSelf This => (TSelf)this;
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证器集合
/// </summary>
internal List<ValidatorBase> Validators { get; }
/// <summary>
/// 获取验证器集合
/// </summary>
/// <returns>
/// <see cref="IReadOnlyList{T}" />
/// </returns>
public IReadOnlyList<ValidatorBase> GetValidators() => Validators;
/// <summary>
/// 批量添加添加验证器
/// </summary>
@@ -206,20 +209,6 @@ public abstract class FluentValidatorBase<T, TSelf>
return This;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <typeparamref name="TSelf" />
/// </returns>
public TSelf WithDisplayName(string? displayName)
{
DisplayName = displayName;
return This;
}
/// <summary>
/// 添加年龄0-120 岁)验证器
/// </summary>
@@ -834,4 +823,12 @@ public abstract class FluentValidatorBase<T, TSelf>
/// </returns>
public TSelf AddAnnotations(ValidationAttribute[] attributes, IDictionary<object, object?>? items) =>
AddValidator(new ValueAnnotationValidator(attributes, _serviceProvider, items));
/// <summary>
/// 构建验证器集合
/// </summary>
/// <returns>
/// <see cref="IReadOnlyList{T}" />
/// </returns>
internal IReadOnlyList<ValidatorBase> Build() => Validators;
}

View File

@@ -33,8 +33,8 @@ namespace Furion.Validation;
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
/// <typeparam name="TProperty">属性类型</typeparam>
public sealed partial class PropertyValidator<T, TProperty> :
FluentValidatorBase<TProperty, PropertyValidator<T, TProperty>>,
public sealed partial class
PropertyValidator<T, TProperty> : FluentValidatorBuilder<TProperty, PropertyValidator<T, TProperty>>,
IObjectValidator<T>
where T : class
{
@@ -81,6 +81,11 @@ public sealed partial class PropertyValidator<T, TProperty> :
/// </remarks>
internal bool? SuppressAnnotationValidation { get; private set; }
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证条件
/// </summary>
@@ -288,6 +293,20 @@ public sealed partial class PropertyValidator<T, TProperty> :
return this;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <see cref="PropertyValidator{T,TProperty}" />
/// </returns>
public PropertyValidator<T, TProperty> WithDisplayName(string? displayName)
{
DisplayName = displayName;
return this;
}
/// <summary>
/// 检查是否应该对该属性执行验证
/// </summary>

View File

@@ -31,7 +31,7 @@ namespace Furion.Validation;
/// 单个值验证器
/// </summary>
/// <typeparam name="T">对象类型</typeparam>
public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
public class ValueValidator<T> : FluentValidatorBuilder<T, ValueValidator<T>>
{
/// <summary>
/// <inheritdoc cref="ValueValidator{T}" />
@@ -44,6 +44,11 @@ public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
{
}
/// <summary>
/// 显示名称
/// </summary>
internal string? DisplayName { get; private set; }
/// <summary>
/// 验证条件
/// </summary>
@@ -145,6 +150,20 @@ public class ValueValidator<T> : FluentValidatorBase<T, ValueValidator<T>>
return this;
}
/// <summary>
/// 设置显示名称
/// </summary>
/// <param name="displayName">显示名称</param>
/// <returns>
/// <see cref="ValueValidator{T}" />
/// </returns>
public ValueValidator<T> WithDisplayName(string? displayName)
{
DisplayName = displayName;
return this;
}
/// <summary>
/// 检查是否应该对该对象执行验证
/// </summary>

View File

@@ -36,12 +36,12 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <summary>
/// 条件和对应的验证器列表
/// </summary>
internal readonly List<(Func<T, bool> Condition, ValidatorBase Validator)> _conditions;
internal readonly List<(Func<T, bool> Condition, IReadOnlyList<ValidatorBase> Validators)> _conditions;
/// <summary>
/// 缺省验证器
/// 缺省验证器集合
/// </summary>
internal readonly ValidatorBase? _defaultValidator;
internal IReadOnlyList<ValidatorBase>? _defaultValidators;
/// <summary>
/// <inheritdoc cref="ConditionalValidator{T}" />
@@ -58,8 +58,8 @@ public class ConditionalValidator<T> : ValidatorBase<T>
// 调用条件构建器配置委托
buildConditions(conditionBuilder);
// 构建条件和默认验证器
(_conditions, _defaultValidator) = conditionBuilder.Build();
// 构建条件和默认验证器集合
(_conditions, _defaultValidators) = conditionBuilder.Build();
ErrorMessageResourceAccessor = () => null!;
}
@@ -67,44 +67,45 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <inheritdoc />
public override bool IsValid(T? instance)
{
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
if (condition(instance!))
{
return validator.IsValid(instance);
return validators.All(u => u.IsValid(instance));
}
}
// 没有匹配条件时使用默认验证器
return _defaultValidator is null || _defaultValidator.IsValid(instance);
// 没有匹配条件时使用默认验证器集合
return _defaultValidators is null || _defaultValidators.All(u => u.IsValid(instance));
}
/// <inheritdoc />
public override List<ValidationResult>? GetValidationResults(T? instance, string name)
{
// 初始化匹配到的验证器
ValidatorBase? matchedValidator = null;
// 初始化匹配到的验证器集合
IReadOnlyList<ValidatorBase>? matchedValidators = null;
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
// ReSharper disable once InvertIf
if (condition(instance!))
{
matchedValidator = validator;
matchedValidators = validators;
break;
}
}
// 没有匹配条件时使用默认验证器
matchedValidator ??= _defaultValidator;
// 没有匹配条件时使用默认验证器集合
matchedValidators ??= _defaultValidators;
// 获取验证结果集合
var validationResults = matchedValidator?.GetValidationResults(instance, name) ?? [];
var validationResults =
matchedValidators?.SelectMany(u => u.GetValidationResults(instance, name) ?? []).ToList();
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
if (validationResults?.Count > 0 && (string?)ErrorMessageString is not null)
{
validationResults.Insert(0, new ValidationResult(FormatErrorMessage(name), [name]));
}
@@ -115,27 +116,37 @@ public class ConditionalValidator<T> : ValidatorBase<T>
/// <inheritdoc />
public override void Validate(T? instance, string name)
{
// 初始化匹配到的验证器
ValidatorBase? matchedValidator = null;
// 初始化匹配到的验证器集合
IReadOnlyList<ValidatorBase>? matchedValidators = null;
// 遍历并查找第一个条件匹配的验证器
foreach (var (condition, validator) in _conditions)
// 遍历并查找第一个条件匹配的验证器集合
foreach (var (condition, validators) in _conditions)
{
// ReSharper disable once InvertIf
if (condition(instance!))
{
matchedValidator = validator;
matchedValidators = validators;
break;
}
}
// 没有匹配条件时使用默认验证器
matchedValidator ??= _defaultValidator;
// 没有匹配条件时使用默认验证器集合
matchedValidators ??= _defaultValidators;
// 空检查
if (matchedValidator is not null && !matchedValidator.IsValid(instance))
if (matchedValidators is null)
{
ThrowValidationException(instance, name, matchedValidator);
return;
}
// 遍历验证器集合
foreach (var validator in matchedValidators)
{
// 检查对象合法性
if (!validator.IsValid(instance))
{
ThrowValidationException(instance, name, validator);
}
}
}