36 lines
1.3 KiB
C#
36 lines
1.3 KiB
C#
using FluentValidation;
|
|
using MediatR;
|
|
|
|
namespace TakeoutSaaS.Application.App.Common.Behaviors;
|
|
|
|
/// <summary>
|
|
/// MediatR 请求验证行为,统一触发 FluentValidation。
|
|
/// </summary>
|
|
/// <typeparam name="TRequest">请求类型。</typeparam>
|
|
/// <typeparam name="TResponse">响应类型。</typeparam>
|
|
public sealed class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, TResponse>
|
|
where TRequest : notnull, IRequest<TResponse>
|
|
{
|
|
private readonly IEnumerable<IValidator<TRequest>> _validators = validators;
|
|
|
|
/// <summary>
|
|
/// 执行验证并在通过时继续后续处理。
|
|
/// </summary>
|
|
public async Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
|
|
{
|
|
if (_validators.Any())
|
|
{
|
|
var context = new ValidationContext<TRequest>(request);
|
|
var validationResults = await Task.WhenAll(_validators.Select(v => v.ValidateAsync(context, cancellationToken)));
|
|
var failures = validationResults.SelectMany(r => r.Errors).Where(f => f is not null).ToList();
|
|
|
|
if (failures.Count > 0)
|
|
{
|
|
throw new ValidationException(failures);
|
|
}
|
|
}
|
|
|
|
return await next();
|
|
}
|
|
}
|