mirror of
https://gitee.com/dotnetchina/Furion.git
synced 2025-12-06 15:59:25 +08:00
😊 改进 新数据验证模块的条件验证器功能
This commit is contained in:
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user