mirror of
https://gitee.com/dotnetchina/Furion.git
synced 2025-12-06 07:49:05 +08:00
Compare commits
4 Commits
6e8ad74854
...
403c3ca68e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
403c3ca68e | ||
|
|
dd599bd1d6 | ||
|
|
4fe76e4dac | ||
|
|
ca3d6f6a55 |
@@ -13,7 +13,8 @@ body:
|
||||
label: 版本号
|
||||
description: 请选择项目使用的 Furion 版本?
|
||||
options:
|
||||
- 4.9.7.220 (最新)
|
||||
- 4.9.7.221 (最新)
|
||||
- 4.9.7.220
|
||||
- 4.9.7.219
|
||||
- 4.9.7.218
|
||||
- 4.9.7.217
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<Version>4.9.7.220</Version>
|
||||
<Version>4.9.7.221</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<!--<Nullable>enable</Nullable>-->
|
||||
<Authors>百小僧</Authors>
|
||||
|
||||
@@ -92,7 +92,17 @@ public static class HttpRemoteClient
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, typeof(HttpRemoteClient));
|
||||
|
||||
// 更新配置委托
|
||||
_configure = configure;
|
||||
_configure = services =>
|
||||
{
|
||||
// 调用自定义配置委托
|
||||
configure(services);
|
||||
|
||||
// 检查 HTTP 远程请求服务是否已注册,若未注册则自动完成注册
|
||||
if (services.All(u => u.ServiceType != typeof(IHttpRemoteService)))
|
||||
{
|
||||
services.AddHttpRemote();
|
||||
}
|
||||
};
|
||||
|
||||
// 重新初始化服务
|
||||
Reinitialize();
|
||||
|
||||
@@ -34,17 +34,14 @@ namespace Furion.Validation;
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <typeparam name="TSelf">派生类型自身类型</typeparam>
|
||||
public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
: FluentValidatorBuilder<T, TSelf>
|
||||
public abstract class FluentValidatorBuilder<T, TSelf> : IValidatorInitializer
|
||||
where TSelf : FluentValidatorBuilder<T, TSelf>
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 高优先级验证器区域的结束索引(同时也是普通验证器区域的起始索引)
|
||||
/// </summary>
|
||||
@@ -60,6 +57,11 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// </summary>
|
||||
internal ValidatorBase? _lastAddedValidator;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="FluentValidatorBuilder{T,TSelf}" />
|
||||
/// </summary>
|
||||
@@ -86,7 +88,12 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
internal FluentValidatorBuilder(IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
Validators = [];
|
||||
}
|
||||
@@ -101,6 +108,21 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// </summary>
|
||||
internal List<ValidatorBase> Validators { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in Validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证器集合
|
||||
/// </summary>
|
||||
@@ -575,8 +597,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new MustUnlessValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new MustUnlessValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -600,8 +621,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new MustValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new MustValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -683,8 +703,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new PredicateValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new PredicateValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -898,8 +917,9 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <returns>
|
||||
/// <typeparamref name="TSelf" />
|
||||
/// </returns>
|
||||
public virtual TSelf AddAnnotations(params ValidationAttribute[] attributes) =>
|
||||
AddValidator(new ValueAnnotationValidator(attributes, _serviceProvider, _items));
|
||||
public virtual TSelf AddAnnotations(params ValidationAttribute[] attributes) => AddValidator(
|
||||
new ValueAnnotationValidator(attributes, null, _items),
|
||||
validator => validator.InitializeServiceProvider(_serviceProvider));
|
||||
|
||||
/// <summary>
|
||||
/// 构建验证器集合
|
||||
@@ -908,4 +928,22 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <see cref="IReadOnlyList{T}" />
|
||||
/// </returns>
|
||||
internal IReadOnlyList<ValidatorBase> Build() => Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext{T}" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext{T}" />
|
||||
/// </returns>
|
||||
internal ValidationContext<T> CreateValidationContext(T value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext<T>(value, null, _items?.AsReadOnly());
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -58,12 +58,12 @@ public sealed class ValidationBuilder
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validatorType);
|
||||
|
||||
// 检查类型是否定义了公开无参构造函数
|
||||
if (!validatorType.HasDefinePublicParameterlessConstructor())
|
||||
// 检查类型是否可实例化
|
||||
if (!validatorType.IsInstantiable())
|
||||
{
|
||||
throw new ArgumentException(
|
||||
// ReSharper disable once LocalizableElement
|
||||
$"Type `{validatorType}` must have a public parameterless constructor to be registered as a validator.",
|
||||
$"Type `{validatorType}` must be a non-abstract, non-static class to be registered as a validator.",
|
||||
nameof(validatorType));
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public sealed class ValidationBuilder
|
||||
|
||||
return AddValidators(assemblies.SelectMany(ass =>
|
||||
(ass?.GetTypes() ?? Enumerable.Empty<Type>()).Where(t =>
|
||||
t.HasDefinePublicParameterlessConstructor() && TryGetValidatedType(t, out _))));
|
||||
t.IsInstantiable() && TryGetValidatedType(t, out _))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,18 +141,44 @@ public sealed class ValidationBuilder
|
||||
foreach (var (validatorType, modelType) in _validatorTypes)
|
||||
{
|
||||
// 注册 IObjectValidator<T> 泛型接口
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient(typeof(IObjectValidator<>).MakeGenericType(modelType),
|
||||
validatorType));
|
||||
services.Add(ServiceDescriptor.Transient(typeof(IObjectValidator<>).MakeGenericType(modelType),
|
||||
provider => CreateValidator(provider, validatorType)));
|
||||
|
||||
// 注册 AbstractValidator<T> 基类
|
||||
// services.TryAddEnumerable(
|
||||
// ServiceDescriptor.Transient(typeof(AbstractValidator<>).MakeGenericType(modelType), validatorType));
|
||||
// services.Add(ServiceDescriptor.Transient(typeof(AbstractValidator<>).MakeGenericType(modelType),
|
||||
// provider => CreateValidator(provider, validatorType)));
|
||||
|
||||
// 注册 IObjectValidator 非泛型接口
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient(typeof(IObjectValidator), validatorType));
|
||||
services.Add(ServiceDescriptor.Transient(typeof(IObjectValidator),
|
||||
provider => CreateValidator(provider, validatorType)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象验证器实例
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">
|
||||
/// <see cref="IServiceProvider" />
|
||||
/// </param>
|
||||
/// <param name="validatorType">对象验证器类型</param>
|
||||
/// <returns>
|
||||
/// <see cref="IObjectValidator" />
|
||||
/// </returns>
|
||||
internal static IObjectValidator CreateValidator(IServiceProvider serviceProvider, Type validatorType)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(serviceProvider);
|
||||
ArgumentNullException.ThrowIfNull(validatorType);
|
||||
|
||||
// 创建对象验证器实例
|
||||
var validator = (IObjectValidator)ActivatorUtilities.CreateInstance(serviceProvider, validatorType);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validator.InitializeServiceProvider(serviceProvider.GetService);
|
||||
|
||||
return validator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否继承自 <see cref="AbstractValidator{T}" /> 抽象基类
|
||||
/// </summary>
|
||||
|
||||
@@ -53,7 +53,7 @@ public static class ValidationExtensions
|
||||
validationResults?.ToList().ToResults();
|
||||
|
||||
/// <summary>
|
||||
/// 使用对象验证器验证当前实例并返回验证结果集合
|
||||
/// 创建对象验证器验证当前实例并返回验证结果集合
|
||||
/// </summary>
|
||||
/// <param name="validationContext">
|
||||
/// <see cref="ValidationContext" />
|
||||
@@ -70,16 +70,44 @@ public static class ValidationExtensions
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validationContext);
|
||||
|
||||
// 解析 IServiceProvider 服务
|
||||
var serviceProvider = validationContext.GetService(typeof(IServiceProvider)) as IServiceProvider;
|
||||
|
||||
// 初始化 ObjectValidator<T> 实例
|
||||
// 初始化 ObjectValidator<T> 实例并禁用属性验证特性验证,避免死循环
|
||||
using var objectValidator = new ObjectValidator<T>(new ValidatorOptions { SuppressAnnotationValidation = true },
|
||||
serviceProvider, validationContext.Items);
|
||||
null, validationContext.Items);
|
||||
|
||||
// 调用自定义配置委托
|
||||
configure?.Invoke(objectValidator);
|
||||
|
||||
return validationContext.ValidateWith(objectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定对象验证器验证当前实例并返回验证结果集合
|
||||
/// </summary>
|
||||
/// <param name="validationContext">
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </param>
|
||||
/// <param name="objectValidator">
|
||||
/// <see cref="AbstractValidator{T}" />
|
||||
/// </param>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <returns>
|
||||
/// <see cref="IEnumerable{T}" />
|
||||
/// </returns>
|
||||
public static IEnumerable<ValidationResult> ValidateWith<T>(this ValidationContext validationContext,
|
||||
ObjectValidator<T> objectValidator) where T : class
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validationContext);
|
||||
|
||||
// 禁用属性验证特性验证,避免死循环
|
||||
objectValidator.ConfigureOptions(options =>
|
||||
{
|
||||
options.SuppressAnnotationValidation = true;
|
||||
});
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
objectValidator.InitializeServiceProvider(validationContext.GetService);
|
||||
|
||||
// 尝试从 Items 中解析规则集列表
|
||||
string?[]? ruleSets = null;
|
||||
if (validationContext.Items.TryGetValue(Constants.RULESETS_KEY, out var ruleSetsObj))
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 对象验证器服务
|
||||
/// </summary>
|
||||
public interface IObjectValidator;
|
||||
public interface IObjectValidator : IValidatorInitializer;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IObjectValidator" />
|
||||
|
||||
@@ -49,8 +49,10 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
/// </summary>
|
||||
internal readonly Stack<string?> _ruleSetStack;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectValidator{T}" />
|
||||
@@ -89,7 +91,13 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
Options = options;
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
|
||||
// 初始化 ObjectAnnotationValidator 实例
|
||||
@@ -209,6 +217,21 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 同步 _annotationValidator 实例 IServiceProvider 委托
|
||||
_annotationValidator.InitializeServiceProvider(serviceProvider);
|
||||
|
||||
// 遍历所有属性验证器并同步 IServiceProvider 委托
|
||||
foreach (var propertyValidator in PropertyValidators)
|
||||
{
|
||||
propertyValidator.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置属性验证器
|
||||
/// </summary>
|
||||
|
||||
@@ -245,8 +245,7 @@ public sealed partial class PropertyValidator<T, TProperty> where T : class
|
||||
var validatorProxy = new ValidatorProxy<T, TValidator>(instance => GetValue(instance),
|
||||
constructorArgsFactory is null
|
||||
? null
|
||||
: instance =>
|
||||
constructorArgsFactory(new ValidationContext<T>(instance, _serviceProvider, _items?.AsReadOnly())));
|
||||
: instance => constructorArgsFactory(CreateValidationContext(instance)));
|
||||
|
||||
// 空检查
|
||||
if (configure is not null)
|
||||
|
||||
@@ -55,8 +55,7 @@ public sealed partial class
|
||||
/// <see cref="ObjectValidator{T}" />
|
||||
/// </param>
|
||||
internal PropertyValidator(Expression<Func<T, TProperty?>> selector, ObjectValidator<T> objectValidator)
|
||||
: base((objectValidator ?? throw new ArgumentNullException(nameof(objectValidator)))._serviceProvider,
|
||||
objectValidator._items)
|
||||
: base(null, (objectValidator ?? throw new ArgumentNullException(nameof(objectValidator)))._items)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
@@ -65,8 +64,10 @@ public sealed partial class
|
||||
_objectValidator = objectValidator;
|
||||
|
||||
// 初始化 PropertyAnnotationValidator 实例
|
||||
_annotationValidator =
|
||||
new PropertyAnnotationValidator<T, TProperty>(selector, _serviceProvider, objectValidator._items);
|
||||
_annotationValidator = new PropertyAnnotationValidator<T, TProperty>(selector, null, objectValidator._items);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
InitializeServiceProvider(objectValidator._serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,6 +207,16 @@ public sealed partial class
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 同步基类 IServiceProvider 委托
|
||||
base.InitializeServiceProvider(serviceProvider);
|
||||
|
||||
// 同步 _annotationValidator 实例 IServiceProvider 委托
|
||||
_annotationValidator.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象验证器
|
||||
/// </summary>
|
||||
@@ -220,6 +231,9 @@ public sealed partial class
|
||||
{
|
||||
_propertyValidator = validator;
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
_propertyValidator?.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -438,4 +452,22 @@ public sealed partial class
|
||||
/// <see cref="string" />
|
||||
/// </returns>
|
||||
internal string GetDisplayName() => _annotationValidator.GetDisplayName(DisplayName);
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext{T}" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext{T}" />
|
||||
/// </returns>
|
||||
internal ValidationContext<T> CreateValidationContext(T value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext<T>(value, null, _items?.AsReadOnly());
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,19 @@
|
||||
// 请访问 https://gitee.com/dotnetchina/Furion 获取更多关于 Furion 项目的许可证和版权信息。
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Furion.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// 验证上下文
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public sealed class ValidationContext<T>
|
||||
public sealed class ValidationContext<T> : IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ValidationContext{T}" />
|
||||
/// </summary>
|
||||
@@ -48,7 +51,13 @@ public sealed class ValidationContext<T>
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
|
||||
Instance = instance;
|
||||
ServiceProvider = serviceProvider;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
Items = items is not null ? new Dictionary<object, object?>(items) : new Dictionary<object, object?>();
|
||||
}
|
||||
|
||||
@@ -57,14 +66,23 @@ public sealed class ValidationContext<T>
|
||||
/// </summary>
|
||||
public T Instance { get; }
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
public IServiceProvider? ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<object, object?> Items { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务
|
||||
/// </summary>
|
||||
/// <param name="serviceType">服务类型</param>
|
||||
/// <returns>
|
||||
/// <see cref="object" />
|
||||
/// </returns>
|
||||
public object? GetService(Type serviceType) => _serviceProvider?.Invoke(serviceType);
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务
|
||||
/// </summary>
|
||||
@@ -72,5 +90,5 @@ public sealed class ValidationContext<T>
|
||||
/// <returns>
|
||||
/// <typeparamref name="TService" />
|
||||
/// </returns>
|
||||
public TService? GetService<TService>() where TService : class => ServiceProvider?.GetService<TService>();
|
||||
public TService? GetService<TService>() where TService : class => (TService?)GetService(typeof(TService));
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 组合验证器
|
||||
/// </summary>
|
||||
public class CompositeValidator : ValidatorBase
|
||||
public class CompositeValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 高优先级验证器列表
|
||||
@@ -73,6 +73,19 @@ public class CompositeValidator : ValidatorBase
|
||||
/// <remarks>默认值为:<see cref="ValidationMode.ValidateAll" />。</remarks>
|
||||
public ValidationMode Mode { get; set; } = ValidationMode.ValidateAll;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in Validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Furion.Validation;
|
||||
/// 条件验证器
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public class ConditionalValidator<T> : ValidatorBase<T>
|
||||
public class ConditionalValidator<T> : ValidatorBase<T>, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 条件和对应的验证器列表
|
||||
@@ -64,6 +64,22 @@ public class ConditionalValidator<T> : ValidatorBase<T>
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 组合所有条件的验证器
|
||||
var validators = (_defaultValidators ?? []).Concat(_conditions.SelectMany(u => u.Validators));
|
||||
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(T? instance)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// 版权信息
|
||||
// 版权归百小僧及百签科技(广东)有限公司所有。
|
||||
// 所有权利保留。
|
||||
// 官方网站:https://baiqian.com
|
||||
//
|
||||
// 许可证信息
|
||||
// Furion 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
|
||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
|
||||
// 官方网站:https://furion.net
|
||||
//
|
||||
// 使用条款
|
||||
// 使用本代码应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 免责声明
|
||||
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害,我们不承担任何责任。
|
||||
//
|
||||
// 其他重要信息
|
||||
// Furion 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
|
||||
// 有关 Furion 项目的其他详细信息,请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
|
||||
//
|
||||
// 更多信息
|
||||
// 请访问 https://gitee.com/dotnetchina/Furion 获取更多关于 Furion 项目的许可证和版权信息。
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace Furion.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// 定义验证器的 <see cref="IServiceProvider" /> 初始化行为
|
||||
/// </summary>
|
||||
public interface IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化(同步) <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"><see cref="IServiceProvider" /> 委托</param>
|
||||
void InitializeServiceProvider(Func<Type, object?>? serviceProvider);
|
||||
}
|
||||
@@ -31,20 +31,25 @@ namespace Furion.Validation;
|
||||
/// 对象验证特性验证器
|
||||
/// </summary>
|
||||
/// <remarks>支持使用 <c>[ValidateNever]</c> 特性来跳过对特定属性的验证,仅限于 ASP.NET Core 应用项目。</remarks>
|
||||
public class ObjectAnnotationValidator : ValidatorBase
|
||||
public class ObjectAnnotationValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectAnnotationValidator" />
|
||||
/// </summary>
|
||||
public ObjectAnnotationValidator() => ErrorMessageResourceAccessor = () => null!;
|
||||
public ObjectAnnotationValidator()
|
||||
: this(null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectAnnotationValidator" />
|
||||
@@ -63,10 +68,15 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// </param>
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public ObjectAnnotationValidator(IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
|
||||
: this()
|
||||
{
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -79,14 +89,16 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// </remarks>
|
||||
public bool ValidateAllProperties { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
return Validator.TryValidateObject(value, new ValidationContext(value, _serviceProvider, _items), null,
|
||||
ValidateAllProperties);
|
||||
return Validator.TryValidateObject(value, CreateValidationContext(value), null, ValidateAllProperties);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -105,8 +117,7 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
* 参考源码:
|
||||
* https://github.com/dotnet/runtime/blob/5535e31a712343a63f5d7d796cd874e563e5ac14/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs#L423-L430
|
||||
*/
|
||||
Validator.TryValidateObject(value, new ValidationContext(value, _serviceProvider, _items), validationResults,
|
||||
ValidateAllProperties);
|
||||
Validator.TryValidateObject(value, CreateValidationContext(value), validationResults, ValidateAllProperties);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -125,8 +136,7 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateObject(value, new ValidationContext(value, _serviceProvider, _items),
|
||||
ValidateAllProperties);
|
||||
Validator.ValidateObject(value, CreateValidationContext(value), ValidateAllProperties);
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -142,4 +152,22 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// <inheritdoc />
|
||||
public override string? FormatErrorMessage(string name) =>
|
||||
(string?)ErrorMessageString is null ? null : base.FormatErrorMessage(name);
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class PropertyAnnotationValidator<T, TProperty> : PropertyAnnotationValid
|
||||
/// 属性验证特性验证器
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
public class PropertyAnnotationValidator<T> : ValidatorBase<T>, IValidatorInitializer
|
||||
where T : class
|
||||
{
|
||||
/// <summary>
|
||||
@@ -121,22 +121,18 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="PropertyAnnotationValidator{T}" />
|
||||
/// </summary>
|
||||
/// <param name="selector">属性选择器</param>
|
||||
public PropertyAnnotationValidator(Expression<Func<T, object?>> selector)
|
||||
: this(selector, null, null)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
|
||||
Property = selector.GetProperty();
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
|
||||
_getter = selector.Compile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,10 +155,21 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public PropertyAnnotationValidator(Expression<Func<T, object?>> selector, IServiceProvider? serviceProvider,
|
||||
IDictionary<object, object?>? items)
|
||||
: this(selector)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
|
||||
Property = selector.GetProperty();
|
||||
_getter = selector.Compile();
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,14 +177,17 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// </summary>
|
||||
public PropertyInfo Property { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(T? instance)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
|
||||
return Validator.TryValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = Property.Name }, null);
|
||||
return Validator.TryValidateProperty(GetValue(instance), CreateValidationContext(instance, Property.Name),
|
||||
null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -192,8 +202,8 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
// 初始化验证结果集合
|
||||
var validationResults = new List<ValidationResult>();
|
||||
|
||||
Validator.TryValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = propertyName }, validationResults);
|
||||
Validator.TryValidateProperty(GetValue(instance), CreateValidationContext(instance, propertyName),
|
||||
validationResults);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -216,8 +226,7 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = propertyName });
|
||||
Validator.ValidateProperty(GetValue(instance), CreateValidationContext(instance, propertyName));
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -256,4 +265,23 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
public string GetDisplayName(string? name) =>
|
||||
name ?? Property.GetCustomAttribute<DisplayAttribute>(false)?.Name ??
|
||||
Property.GetCustomAttribute<DisplayNameAttribute>(false)?.DisplayName ?? Property.Name;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <param name="memberName">成员名称</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value, string? memberName)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items) { MemberName = memberName };
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace Furion.Validation;
|
||||
/// <typeparam name="TValidator">
|
||||
/// <see cref="ValidatorBase" />
|
||||
/// </typeparam>
|
||||
public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable
|
||||
public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable, IValidatorInitializer
|
||||
where TValidator : ValidatorBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -65,6 +65,17 @@ public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 检查验证器是否实现 IValidatorInitializer 接口
|
||||
if (Validator is IValidatorInitializer initializer)
|
||||
{
|
||||
// 同步 IServiceProvider 委托
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置验证器实例
|
||||
/// </summary>
|
||||
|
||||
@@ -30,15 +30,17 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 单个值验证特性验证器
|
||||
/// </summary>
|
||||
public class ValueAnnotationValidator : ValidatorBase
|
||||
public class ValueAnnotationValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ValueAnnotationValidator" />
|
||||
@@ -46,19 +48,8 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <param name="attributes">验证特性列表</param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public ValueAnnotationValidator(params ValidationAttribute[] attributes)
|
||||
: this(attributes, null, null)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(attributes);
|
||||
|
||||
// 确保数组元素不存在 null 值
|
||||
if (attributes.Any(u => (ValidationAttribute?)u is null))
|
||||
{
|
||||
// ReSharper disable once LocalizableElement
|
||||
throw new ArgumentException("Attributes cannot contain null elements.", nameof(attributes));
|
||||
}
|
||||
|
||||
Attributes = attributes;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,10 +72,27 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public ValueAnnotationValidator(ValidationAttribute[] attributes, IServiceProvider? serviceProvider,
|
||||
IDictionary<object, object?>? items)
|
||||
: this(attributes)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(attributes);
|
||||
|
||||
// 确保数组元素不存在 null 值
|
||||
if (attributes.Any(u => (ValidationAttribute?)u is null))
|
||||
{
|
||||
// ReSharper disable once LocalizableElement
|
||||
throw new ArgumentException("Attributes cannot contain null elements.", nameof(attributes));
|
||||
}
|
||||
|
||||
Attributes = attributes;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,10 +100,12 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// </summary>
|
||||
public ValidationAttribute[] Attributes { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value) =>
|
||||
Validator.TryValidateValue(value, new ValidationContext(new object(), _serviceProvider, _items), null,
|
||||
Attributes);
|
||||
Validator.TryValidateValue(value, CreateValidationContext(new object(), null), null, Attributes);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override List<ValidationResult>? GetValidationResults(object? value, string name)
|
||||
@@ -103,9 +113,8 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
// 初始化属性名称和验证结果集合
|
||||
var (memberName, validationResults) = (GetMemberName(name), new List<ValidationResult>());
|
||||
|
||||
Validator.TryValidateValue(value,
|
||||
new ValidationContext(new object(), _serviceProvider, _items) { MemberName = memberName },
|
||||
validationResults, Attributes);
|
||||
Validator.TryValidateValue(value, CreateValidationContext(new object(), memberName), validationResults,
|
||||
Attributes);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -124,8 +133,7 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateValue(value,
|
||||
new ValidationContext(new object(), _serviceProvider, _items) { MemberName = memberName }, Attributes);
|
||||
Validator.ValidateValue(value, CreateValidationContext(new object(), memberName), Attributes);
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -147,4 +155,23 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <see cref="string" />
|
||||
/// </returns>
|
||||
internal static string GetMemberName(string name) => string.IsNullOrEmpty(name) ? "Value" : name;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <param name="memberName">成员名称</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value, string? memberName)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items) { MemberName = memberName };
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,17 @@ public static class HttpRemoteClient
|
||||
ObjectDisposedException.ThrowIf(_isDisposed, typeof(HttpRemoteClient));
|
||||
|
||||
// 更新配置委托
|
||||
_configure = configure;
|
||||
_configure = services =>
|
||||
{
|
||||
// 调用自定义配置委托
|
||||
configure(services);
|
||||
|
||||
// 检查 HTTP 远程请求服务是否已注册,若未注册则自动完成注册
|
||||
if (services.All(u => u.ServiceType != typeof(IHttpRemoteService)))
|
||||
{
|
||||
services.AddHttpRemote();
|
||||
}
|
||||
};
|
||||
|
||||
// 重新初始化服务
|
||||
Reinitialize();
|
||||
|
||||
@@ -34,17 +34,14 @@ namespace Furion.Validation;
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <typeparam name="TSelf">派生类型自身类型</typeparam>
|
||||
public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
: FluentValidatorBuilder<T, TSelf>
|
||||
public abstract class FluentValidatorBuilder<T, TSelf> : IValidatorInitializer
|
||||
where TSelf : FluentValidatorBuilder<T, TSelf>
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 高优先级验证器区域的结束索引(同时也是普通验证器区域的起始索引)
|
||||
/// </summary>
|
||||
@@ -60,6 +57,11 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// </summary>
|
||||
internal ValidatorBase? _lastAddedValidator;
|
||||
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="FluentValidatorBuilder{T,TSelf}" />
|
||||
/// </summary>
|
||||
@@ -86,7 +88,12 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
internal FluentValidatorBuilder(IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
Validators = [];
|
||||
}
|
||||
@@ -101,6 +108,21 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// </summary>
|
||||
internal List<ValidatorBase> Validators { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in Validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取验证器集合
|
||||
/// </summary>
|
||||
@@ -575,8 +597,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new MustUnlessValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new MustUnlessValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -600,8 +621,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new MustValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new MustValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -683,8 +703,7 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(condition);
|
||||
|
||||
return AddValidator(new PredicateValidator<T>(u =>
|
||||
condition(u, new ValidationContext<T>(u, _serviceProvider, _items?.AsReadOnly()))));
|
||||
return AddValidator(new PredicateValidator<T>(u => condition(u, CreateValidationContext(u))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -898,8 +917,9 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <returns>
|
||||
/// <typeparamref name="TSelf" />
|
||||
/// </returns>
|
||||
public virtual TSelf AddAnnotations(params ValidationAttribute[] attributes) =>
|
||||
AddValidator(new ValueAnnotationValidator(attributes, _serviceProvider, _items));
|
||||
public virtual TSelf AddAnnotations(params ValidationAttribute[] attributes) => AddValidator(
|
||||
new ValueAnnotationValidator(attributes, null, _items),
|
||||
validator => validator.InitializeServiceProvider(_serviceProvider));
|
||||
|
||||
/// <summary>
|
||||
/// 构建验证器集合
|
||||
@@ -908,4 +928,22 @@ public abstract class FluentValidatorBuilder<T, TSelf> where TSelf
|
||||
/// <see cref="IReadOnlyList{T}" />
|
||||
/// </returns>
|
||||
internal IReadOnlyList<ValidatorBase> Build() => Validators;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext{T}" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext{T}" />
|
||||
/// </returns>
|
||||
internal ValidationContext<T> CreateValidationContext(T value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext<T>(value, null, _items?.AsReadOnly());
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -58,12 +58,12 @@ public sealed class ValidationBuilder
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validatorType);
|
||||
|
||||
// 检查类型是否定义了公开无参构造函数
|
||||
if (!validatorType.HasDefinePublicParameterlessConstructor())
|
||||
// 检查类型是否可实例化
|
||||
if (!validatorType.IsInstantiable())
|
||||
{
|
||||
throw new ArgumentException(
|
||||
// ReSharper disable once LocalizableElement
|
||||
$"Type `{validatorType}` must have a public parameterless constructor to be registered as a validator.",
|
||||
$"Type `{validatorType}` must be a non-abstract, non-static class to be registered as a validator.",
|
||||
nameof(validatorType));
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ public sealed class ValidationBuilder
|
||||
|
||||
return AddValidators(assemblies.SelectMany(ass =>
|
||||
(ass?.GetTypes() ?? Enumerable.Empty<Type>()).Where(t =>
|
||||
t.HasDefinePublicParameterlessConstructor() && TryGetValidatedType(t, out _))));
|
||||
t.IsInstantiable() && TryGetValidatedType(t, out _))));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -141,18 +141,44 @@ public sealed class ValidationBuilder
|
||||
foreach (var (validatorType, modelType) in _validatorTypes)
|
||||
{
|
||||
// 注册 IObjectValidator<T> 泛型接口
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient(typeof(IObjectValidator<>).MakeGenericType(modelType),
|
||||
validatorType));
|
||||
services.Add(ServiceDescriptor.Transient(typeof(IObjectValidator<>).MakeGenericType(modelType),
|
||||
provider => CreateValidator(provider, validatorType)));
|
||||
|
||||
// 注册 AbstractValidator<T> 基类
|
||||
// services.TryAddEnumerable(
|
||||
// ServiceDescriptor.Transient(typeof(AbstractValidator<>).MakeGenericType(modelType), validatorType));
|
||||
// services.Add(ServiceDescriptor.Transient(typeof(AbstractValidator<>).MakeGenericType(modelType),
|
||||
// provider => CreateValidator(provider, validatorType)));
|
||||
|
||||
// 注册 IObjectValidator 非泛型接口
|
||||
services.TryAddEnumerable(ServiceDescriptor.Transient(typeof(IObjectValidator), validatorType));
|
||||
services.Add(ServiceDescriptor.Transient(typeof(IObjectValidator),
|
||||
provider => CreateValidator(provider, validatorType)));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 创建对象验证器实例
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider">
|
||||
/// <see cref="IServiceProvider" />
|
||||
/// </param>
|
||||
/// <param name="validatorType">对象验证器类型</param>
|
||||
/// <returns>
|
||||
/// <see cref="IObjectValidator" />
|
||||
/// </returns>
|
||||
internal static IObjectValidator CreateValidator(IServiceProvider serviceProvider, Type validatorType)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(serviceProvider);
|
||||
ArgumentNullException.ThrowIfNull(validatorType);
|
||||
|
||||
// 创建对象验证器实例
|
||||
var validator = (IObjectValidator)ActivatorUtilities.CreateInstance(serviceProvider, validatorType);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validator.InitializeServiceProvider(serviceProvider.GetService);
|
||||
|
||||
return validator;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查是否继承自 <see cref="AbstractValidator{T}" /> 抽象基类
|
||||
/// </summary>
|
||||
|
||||
@@ -53,7 +53,7 @@ public static class ValidationExtensions
|
||||
validationResults?.ToList().ToResults();
|
||||
|
||||
/// <summary>
|
||||
/// 使用对象验证器验证当前实例并返回验证结果集合
|
||||
/// 创建对象验证器验证当前实例并返回验证结果集合
|
||||
/// </summary>
|
||||
/// <param name="validationContext">
|
||||
/// <see cref="ValidationContext" />
|
||||
@@ -70,16 +70,44 @@ public static class ValidationExtensions
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validationContext);
|
||||
|
||||
// 解析 IServiceProvider 服务
|
||||
var serviceProvider = validationContext.GetService(typeof(IServiceProvider)) as IServiceProvider;
|
||||
|
||||
// 初始化 ObjectValidator<T> 实例
|
||||
// 初始化 ObjectValidator<T> 实例并禁用属性验证特性验证,避免死循环
|
||||
using var objectValidator = new ObjectValidator<T>(new ValidatorOptions { SuppressAnnotationValidation = true },
|
||||
serviceProvider, validationContext.Items);
|
||||
null, validationContext.Items);
|
||||
|
||||
// 调用自定义配置委托
|
||||
configure?.Invoke(objectValidator);
|
||||
|
||||
return validationContext.ValidateWith(objectValidator);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 使用指定对象验证器验证当前实例并返回验证结果集合
|
||||
/// </summary>
|
||||
/// <param name="validationContext">
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </param>
|
||||
/// <param name="objectValidator">
|
||||
/// <see cref="AbstractValidator{T}" />
|
||||
/// </param>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
/// <returns>
|
||||
/// <see cref="IEnumerable{T}" />
|
||||
/// </returns>
|
||||
public static IEnumerable<ValidationResult> ValidateWith<T>(this ValidationContext validationContext,
|
||||
ObjectValidator<T> objectValidator) where T : class
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(validationContext);
|
||||
|
||||
// 禁用属性验证特性验证,避免死循环
|
||||
objectValidator.ConfigureOptions(options =>
|
||||
{
|
||||
options.SuppressAnnotationValidation = true;
|
||||
});
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
objectValidator.InitializeServiceProvider(validationContext.GetService);
|
||||
|
||||
// 尝试从 Items 中解析规则集列表
|
||||
string?[]? ruleSets = null;
|
||||
if (validationContext.Items.TryGetValue(Constants.RULESETS_KEY, out var ruleSetsObj))
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 对象验证器服务
|
||||
/// </summary>
|
||||
public interface IObjectValidator;
|
||||
public interface IObjectValidator : IValidatorInitializer;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="IObjectValidator" />
|
||||
|
||||
@@ -49,8 +49,10 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
/// </summary>
|
||||
internal readonly Stack<string?> _ruleSetStack;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectValidator{T}" />
|
||||
@@ -89,7 +91,13 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
ArgumentNullException.ThrowIfNull(options);
|
||||
|
||||
Options = options;
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
|
||||
// 初始化 ObjectAnnotationValidator 实例
|
||||
@@ -209,6 +217,21 @@ public class ObjectValidator<T> : IObjectValidator<T>, IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
_serviceProvider = serviceProvider;
|
||||
|
||||
// 同步 _annotationValidator 实例 IServiceProvider 委托
|
||||
_annotationValidator.InitializeServiceProvider(serviceProvider);
|
||||
|
||||
// 遍历所有属性验证器并同步 IServiceProvider 委托
|
||||
foreach (var propertyValidator in PropertyValidators)
|
||||
{
|
||||
propertyValidator.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置属性验证器
|
||||
/// </summary>
|
||||
|
||||
@@ -245,8 +245,7 @@ public sealed partial class PropertyValidator<T, TProperty> where T : class
|
||||
var validatorProxy = new ValidatorProxy<T, TValidator>(instance => GetValue(instance),
|
||||
constructorArgsFactory is null
|
||||
? null
|
||||
: instance =>
|
||||
constructorArgsFactory(new ValidationContext<T>(instance, _serviceProvider, _items?.AsReadOnly())));
|
||||
: instance => constructorArgsFactory(CreateValidationContext(instance)));
|
||||
|
||||
// 空检查
|
||||
if (configure is not null)
|
||||
|
||||
@@ -55,8 +55,7 @@ public sealed partial class
|
||||
/// <see cref="ObjectValidator{T}" />
|
||||
/// </param>
|
||||
internal PropertyValidator(Expression<Func<T, TProperty?>> selector, ObjectValidator<T> objectValidator)
|
||||
: base((objectValidator ?? throw new ArgumentNullException(nameof(objectValidator)))._serviceProvider,
|
||||
objectValidator._items)
|
||||
: base(null, (objectValidator ?? throw new ArgumentNullException(nameof(objectValidator)))._items)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
@@ -65,8 +64,10 @@ public sealed partial class
|
||||
_objectValidator = objectValidator;
|
||||
|
||||
// 初始化 PropertyAnnotationValidator 实例
|
||||
_annotationValidator =
|
||||
new PropertyAnnotationValidator<T, TProperty>(selector, _serviceProvider, objectValidator._items);
|
||||
_annotationValidator = new PropertyAnnotationValidator<T, TProperty>(selector, null, objectValidator._items);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
InitializeServiceProvider(objectValidator._serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -206,6 +207,16 @@ public sealed partial class
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 同步基类 IServiceProvider 委托
|
||||
base.InitializeServiceProvider(serviceProvider);
|
||||
|
||||
// 同步 _annotationValidator 实例 IServiceProvider 委托
|
||||
_annotationValidator.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置对象验证器
|
||||
/// </summary>
|
||||
@@ -220,6 +231,9 @@ public sealed partial class
|
||||
{
|
||||
_propertyValidator = validator;
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
_propertyValidator?.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -438,4 +452,22 @@ public sealed partial class
|
||||
/// <see cref="string" />
|
||||
/// </returns>
|
||||
internal string GetDisplayName() => _annotationValidator.GetDisplayName(DisplayName);
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext{T}" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext{T}" />
|
||||
/// </returns>
|
||||
internal ValidationContext<T> CreateValidationContext(T value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext<T>(value, null, _items?.AsReadOnly());
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -23,16 +23,19 @@
|
||||
// 请访问 https://gitee.com/dotnetchina/Furion 获取更多关于 Furion 项目的许可证和版权信息。
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace Furion.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// 验证上下文
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public sealed class ValidationContext<T>
|
||||
public sealed class ValidationContext<T> : IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ValidationContext{T}" />
|
||||
/// </summary>
|
||||
@@ -48,7 +51,13 @@ public sealed class ValidationContext<T>
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
|
||||
Instance = instance;
|
||||
ServiceProvider = serviceProvider;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
Items = items is not null ? new Dictionary<object, object?>(items) : new Dictionary<object, object?>();
|
||||
}
|
||||
|
||||
@@ -57,14 +66,23 @@ public sealed class ValidationContext<T>
|
||||
/// </summary>
|
||||
public T Instance { get; }
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
public IServiceProvider? ServiceProvider { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<object, object?> Items { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务
|
||||
/// </summary>
|
||||
/// <param name="serviceType">服务类型</param>
|
||||
/// <returns>
|
||||
/// <see cref="object" />
|
||||
/// </returns>
|
||||
public object? GetService(Type serviceType) => _serviceProvider?.Invoke(serviceType);
|
||||
|
||||
/// <summary>
|
||||
/// 解析服务
|
||||
/// </summary>
|
||||
@@ -72,5 +90,5 @@ public sealed class ValidationContext<T>
|
||||
/// <returns>
|
||||
/// <typeparamref name="TService" />
|
||||
/// </returns>
|
||||
public TService? GetService<TService>() where TService : class => ServiceProvider?.GetService<TService>();
|
||||
public TService? GetService<TService>() where TService : class => (TService?)GetService(typeof(TService));
|
||||
}
|
||||
@@ -30,7 +30,7 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 组合验证器
|
||||
/// </summary>
|
||||
public class CompositeValidator : ValidatorBase
|
||||
public class CompositeValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 高优先级验证器列表
|
||||
@@ -73,6 +73,19 @@ public class CompositeValidator : ValidatorBase
|
||||
/// <remarks>默认值为:<see cref="ValidationMode.ValidateAll" />。</remarks>
|
||||
public ValidationMode Mode { get; set; } = ValidationMode.ValidateAll;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in Validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@ namespace Furion.Validation;
|
||||
/// 条件验证器
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public class ConditionalValidator<T> : ValidatorBase<T>
|
||||
public class ConditionalValidator<T> : ValidatorBase<T>, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 条件和对应的验证器列表
|
||||
@@ -64,6 +64,22 @@ public class ConditionalValidator<T> : ValidatorBase<T>
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 组合所有条件的验证器
|
||||
var validators = (_defaultValidators ?? []).Concat(_conditions.SelectMany(u => u.Validators));
|
||||
|
||||
// 遍历所有实现 IValidatorInitializer 接口的验证器并同步 IServiceProvider 委托
|
||||
foreach (var validator in validators)
|
||||
{
|
||||
if (validator is IValidatorInitializer initializer)
|
||||
{
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(T? instance)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
// ------------------------------------------------------------------------
|
||||
// 版权信息
|
||||
// 版权归百小僧及百签科技(广东)有限公司所有。
|
||||
// 所有权利保留。
|
||||
// 官方网站:https://baiqian.com
|
||||
//
|
||||
// 许可证信息
|
||||
// Furion 项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。
|
||||
// 许可证的完整文本可以在源代码树根目录中的 LICENSE-APACHE 和 LICENSE-MIT 文件中找到。
|
||||
// 官方网站:https://furion.net
|
||||
//
|
||||
// 使用条款
|
||||
// 使用本代码应遵守相关法律法规和许可证的要求。
|
||||
//
|
||||
// 免责声明
|
||||
// 对于因使用本代码而产生的任何直接、间接、偶然、特殊或后果性损害,我们不承担任何责任。
|
||||
//
|
||||
// 其他重要信息
|
||||
// Furion 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。
|
||||
// 有关 Furion 项目的其他详细信息,请参阅位于源代码树根目录中的 COPYRIGHT 和 DISCLAIMER 文件。
|
||||
//
|
||||
// 更多信息
|
||||
// 请访问 https://gitee.com/dotnetchina/Furion 获取更多关于 Furion 项目的许可证和版权信息。
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
namespace Furion.Validation;
|
||||
|
||||
/// <summary>
|
||||
/// 定义验证器的 <see cref="IServiceProvider" /> 初始化行为
|
||||
/// </summary>
|
||||
public interface IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 初始化(同步) <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
/// <param name="serviceProvider"><see cref="IServiceProvider" /> 委托</param>
|
||||
void InitializeServiceProvider(Func<Type, object?>? serviceProvider);
|
||||
}
|
||||
@@ -31,20 +31,25 @@ namespace Furion.Validation;
|
||||
/// 对象验证特性验证器
|
||||
/// </summary>
|
||||
/// <remarks>支持使用 <c>[ValidateNever]</c> 特性来跳过对特定属性的验证,仅限于 ASP.NET Core 应用项目。</remarks>
|
||||
public class ObjectAnnotationValidator : ValidatorBase
|
||||
public class ObjectAnnotationValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectAnnotationValidator" />
|
||||
/// </summary>
|
||||
public ObjectAnnotationValidator() => ErrorMessageResourceAccessor = () => null!;
|
||||
public ObjectAnnotationValidator()
|
||||
: this(null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ObjectAnnotationValidator" />
|
||||
@@ -63,10 +68,15 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// </param>
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public ObjectAnnotationValidator(IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
|
||||
: this()
|
||||
{
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -79,14 +89,16 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// </remarks>
|
||||
public bool ValidateAllProperties { get; set; } = true;
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(value);
|
||||
|
||||
return Validator.TryValidateObject(value, new ValidationContext(value, _serviceProvider, _items), null,
|
||||
ValidateAllProperties);
|
||||
return Validator.TryValidateObject(value, CreateValidationContext(value), null, ValidateAllProperties);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -105,8 +117,7 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
* 参考源码:
|
||||
* https://github.com/dotnet/runtime/blob/5535e31a712343a63f5d7d796cd874e563e5ac14/src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs#L423-L430
|
||||
*/
|
||||
Validator.TryValidateObject(value, new ValidationContext(value, _serviceProvider, _items), validationResults,
|
||||
ValidateAllProperties);
|
||||
Validator.TryValidateObject(value, CreateValidationContext(value), validationResults, ValidateAllProperties);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -125,8 +136,7 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateObject(value, new ValidationContext(value, _serviceProvider, _items),
|
||||
ValidateAllProperties);
|
||||
Validator.ValidateObject(value, CreateValidationContext(value), ValidateAllProperties);
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -142,4 +152,22 @@ public class ObjectAnnotationValidator : ValidatorBase
|
||||
/// <inheritdoc />
|
||||
public override string? FormatErrorMessage(string name) =>
|
||||
(string?)ErrorMessageString is null ? null : base.FormatErrorMessage(name);
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items);
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -108,7 +108,7 @@ public class PropertyAnnotationValidator<T, TProperty> : PropertyAnnotationValid
|
||||
/// 属性验证特性验证器
|
||||
/// </summary>
|
||||
/// <typeparam name="T">对象类型</typeparam>
|
||||
public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
public class PropertyAnnotationValidator<T> : ValidatorBase<T>, IValidatorInitializer
|
||||
where T : class
|
||||
{
|
||||
/// <summary>
|
||||
@@ -121,22 +121,18 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="PropertyAnnotationValidator{T}" />
|
||||
/// </summary>
|
||||
/// <param name="selector">属性选择器</param>
|
||||
public PropertyAnnotationValidator(Expression<Func<T, object?>> selector)
|
||||
: this(selector, null, null)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
|
||||
Property = selector.GetProperty();
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
|
||||
_getter = selector.Compile();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -159,10 +155,21 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public PropertyAnnotationValidator(Expression<Func<T, object?>> selector, IServiceProvider? serviceProvider,
|
||||
IDictionary<object, object?>? items)
|
||||
: this(selector)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(selector);
|
||||
|
||||
Property = selector.GetProperty();
|
||||
_getter = selector.Compile();
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -170,14 +177,17 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
/// </summary>
|
||||
public PropertyInfo Property { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(T? instance)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(instance);
|
||||
|
||||
return Validator.TryValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = Property.Name }, null);
|
||||
return Validator.TryValidateProperty(GetValue(instance), CreateValidationContext(instance, Property.Name),
|
||||
null);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -192,8 +202,8 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
// 初始化验证结果集合
|
||||
var validationResults = new List<ValidationResult>();
|
||||
|
||||
Validator.TryValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = propertyName }, validationResults);
|
||||
Validator.TryValidateProperty(GetValue(instance), CreateValidationContext(instance, propertyName),
|
||||
validationResults);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -216,8 +226,7 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateProperty(GetValue(instance),
|
||||
new ValidationContext(instance, _serviceProvider, _items) { MemberName = propertyName });
|
||||
Validator.ValidateProperty(GetValue(instance), CreateValidationContext(instance, propertyName));
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -256,4 +265,23 @@ public class PropertyAnnotationValidator<T> : ValidatorBase<T>
|
||||
public string GetDisplayName(string? name) =>
|
||||
name ?? Property.GetCustomAttribute<DisplayAttribute>(false)?.Name ??
|
||||
Property.GetCustomAttribute<DisplayNameAttribute>(false)?.DisplayName ?? Property.Name;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <param name="memberName">成员名称</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value, string? memberName)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items) { MemberName = memberName };
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -37,7 +37,7 @@ namespace Furion.Validation;
|
||||
/// <typeparam name="TValidator">
|
||||
/// <see cref="ValidatorBase" />
|
||||
/// </typeparam>
|
||||
public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable
|
||||
public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable, IValidatorInitializer
|
||||
where TValidator : ValidatorBase
|
||||
{
|
||||
/// <summary>
|
||||
@@ -65,6 +65,17 @@ public class ValidatorProxy<TValidator> : ValidatorBase, IDisposable
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider)
|
||||
{
|
||||
// 检查验证器是否实现 IValidatorInitializer 接口
|
||||
if (Validator is IValidatorInitializer initializer)
|
||||
{
|
||||
// 同步 IServiceProvider 委托
|
||||
initializer.InitializeServiceProvider(serviceProvider);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 配置验证器实例
|
||||
/// </summary>
|
||||
|
||||
@@ -30,15 +30,17 @@ namespace Furion.Validation;
|
||||
/// <summary>
|
||||
/// 单个值验证特性验证器
|
||||
/// </summary>
|
||||
public class ValueAnnotationValidator : ValidatorBase
|
||||
public class ValueAnnotationValidator : ValidatorBase, IValidatorInitializer
|
||||
{
|
||||
/// <summary>
|
||||
/// 验证上下文数据
|
||||
/// </summary>
|
||||
internal readonly IDictionary<object, object?>? _items;
|
||||
|
||||
/// <inheritdoc cref="IServiceProvider" />
|
||||
internal readonly IServiceProvider? _serviceProvider;
|
||||
/// <summary>
|
||||
/// <see cref="IServiceProvider" /> 委托
|
||||
/// </summary>
|
||||
internal Func<Type, object?>? _serviceProvider;
|
||||
|
||||
/// <summary>
|
||||
/// <inheritdoc cref="ValueAnnotationValidator" />
|
||||
@@ -46,19 +48,8 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <param name="attributes">验证特性列表</param>
|
||||
/// <exception cref="ArgumentException"></exception>
|
||||
public ValueAnnotationValidator(params ValidationAttribute[] attributes)
|
||||
: this(attributes, null, null)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(attributes);
|
||||
|
||||
// 确保数组元素不存在 null 值
|
||||
if (attributes.Any(u => (ValidationAttribute?)u is null))
|
||||
{
|
||||
// ReSharper disable once LocalizableElement
|
||||
throw new ArgumentException("Attributes cannot contain null elements.", nameof(attributes));
|
||||
}
|
||||
|
||||
Attributes = attributes;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -81,10 +72,27 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <param name="items">验证上下文数据</param>
|
||||
public ValueAnnotationValidator(ValidationAttribute[] attributes, IServiceProvider? serviceProvider,
|
||||
IDictionary<object, object?>? items)
|
||||
: this(attributes)
|
||||
{
|
||||
// 空检查
|
||||
ArgumentNullException.ThrowIfNull(attributes);
|
||||
|
||||
// 确保数组元素不存在 null 值
|
||||
if (attributes.Any(u => (ValidationAttribute?)u is null))
|
||||
{
|
||||
// ReSharper disable once LocalizableElement
|
||||
throw new ArgumentException("Attributes cannot contain null elements.", nameof(attributes));
|
||||
}
|
||||
|
||||
Attributes = attributes;
|
||||
|
||||
// 空检查
|
||||
if (serviceProvider is not null)
|
||||
{
|
||||
_serviceProvider = serviceProvider.GetService;
|
||||
}
|
||||
|
||||
_items = items;
|
||||
_serviceProvider = serviceProvider;
|
||||
ErrorMessageResourceAccessor = () => null!;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -92,10 +100,12 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// </summary>
|
||||
public ValidationAttribute[] Attributes { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public void InitializeServiceProvider(Func<Type, object?>? serviceProvider) => _serviceProvider = serviceProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public override bool IsValid(object? value) =>
|
||||
Validator.TryValidateValue(value, new ValidationContext(new object(), _serviceProvider, _items), null,
|
||||
Attributes);
|
||||
Validator.TryValidateValue(value, CreateValidationContext(new object(), null), null, Attributes);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override List<ValidationResult>? GetValidationResults(object? value, string name)
|
||||
@@ -103,9 +113,8 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
// 初始化属性名称和验证结果集合
|
||||
var (memberName, validationResults) = (GetMemberName(name), new List<ValidationResult>());
|
||||
|
||||
Validator.TryValidateValue(value,
|
||||
new ValidationContext(new object(), _serviceProvider, _items) { MemberName = memberName },
|
||||
validationResults, Attributes);
|
||||
Validator.TryValidateValue(value, CreateValidationContext(new object(), memberName), validationResults,
|
||||
Attributes);
|
||||
|
||||
// 如果验证未通过且配置了自定义错误信息,则在首部添加自定义错误信息
|
||||
if (validationResults.Count > 0 && (string?)ErrorMessageString is not null)
|
||||
@@ -124,8 +133,7 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
|
||||
try
|
||||
{
|
||||
Validator.ValidateValue(value,
|
||||
new ValidationContext(new object(), _serviceProvider, _items) { MemberName = memberName }, Attributes);
|
||||
Validator.ValidateValue(value, CreateValidationContext(new object(), memberName), Attributes);
|
||||
}
|
||||
// 如果验证未通过且配置了自定义错误信息,则重新抛出异常
|
||||
catch (ValidationException e) when (ErrorMessageString is not null)
|
||||
@@ -147,4 +155,23 @@ public class ValueAnnotationValidator : ValidatorBase
|
||||
/// <see cref="string" />
|
||||
/// </returns>
|
||||
internal static string GetMemberName(string name) => string.IsNullOrEmpty(name) ? "Value" : name;
|
||||
|
||||
/// <summary>
|
||||
/// 创建 <see cref="ValidationContext" /> 实例
|
||||
/// </summary>
|
||||
/// <param name="value">对象</param>
|
||||
/// <param name="memberName">成员名称</param>
|
||||
/// <returns>
|
||||
/// <see cref="ValidationContext" />
|
||||
/// </returns>
|
||||
internal ValidationContext CreateValidationContext(object value, string? memberName)
|
||||
{
|
||||
// 初始化 ValidationContext 实例
|
||||
var validationContext = new ValidationContext(value, null, _items) { MemberName = memberName };
|
||||
|
||||
// 同步 IServiceProvider 委托
|
||||
validationContext.InitializeServiceProvider(_serviceProvider!);
|
||||
|
||||
return validationContext;
|
||||
}
|
||||
}
|
||||
@@ -11,8 +11,8 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.Api</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Api 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.App</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Mvc/Api 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.Blazor.App</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Blazor App 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.Blazor</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Blazor 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.BlazorWithWebApi</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Blazor和WebApi 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.Mvc</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Mvc 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.Razor</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 Razor Pages 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.Template.RazorWithWebApi</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 框架快速搭建 RazorPages和WebApi 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.Api</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Api 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.App</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Mvc/Api 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.Blazor.App</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Blazor App 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,9 +7,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.Blazor</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Blazor 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.BlazorWithWebApi</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Blazor和WebApi 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.Mvc</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Mvc 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.Razor</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 Razor Pages 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -7,8 +7,8 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">
|
||||
<metadata>
|
||||
<id>Furion.SqlSugar.Template.RazorWithWebApi</id>
|
||||
<version>4.9.7.220</version>
|
||||
<version>4.9.7.221</version>
|
||||
<description>基于 Furion 和 SqlSugar 框架快速搭建 RazorPages和WebApi 多层架构模板。</description>
|
||||
<authors>百小僧</authors>
|
||||
<packageTypes>
|
||||
|
||||
@@ -12,9 +12,9 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Extras.Authentication.JwtBearer" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Extras.ObjectMapper.Mapster" Version="4.9.7.221" />
|
||||
<PackageReference Include="Furion.Pure" Version="4.9.7.221" />
|
||||
<PackageReference Include="SqlSugarCore" Version="5.1.4.210" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<PropertyGroup>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<TargetFrameworks>net8.0;net9.0;net10.0</TargetFrameworks>
|
||||
<Version>4.9.7.220</Version>
|
||||
<Version>4.9.7.221</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<!--<Nullable>enable</Nullable>-->
|
||||
<Authors>百小僧</Authors>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Furion.Tools.CommandLine" Version="4.9.7.220" />
|
||||
<PackageReference Include="Furion.Tools.CommandLine" Version="4.9.7.221" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -96,7 +96,7 @@ function AddXmlCommentsToProperties($content, $commentsDictionary) {
|
||||
return $modifiedContent
|
||||
}
|
||||
|
||||
$FurTools = "Furion Tools v4.9.7.220";
|
||||
$FurTools = "Furion Tools v4.9.7.221";
|
||||
|
||||
# 输出信息
|
||||
$copyright = @"
|
||||
|
||||
Reference in New Issue
Block a user