我将通过
LangExt 库用
Result<T>
替换所有异常。问题是 ValidationBehavior
甚至没有被触发。它用于在方法签名曾经是 public class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>
时触发。那么我如何注册 ValidationBehavior
以便它被触发,这样我就不必手动指定 AbstractValidator
类?
builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.AddMediatR(configure =>
{
configure.RegisterServicesFromAssemblyContaining<Program>();
configure.AddRequestPreProcessor(typeof(IRequestPreProcessor<>), typeof(LoggingBehavior<>));
configure.AddBehavior(typeof(IPipelineBehavior<,>), typeof(ValidationBehavior<,>));
configure.AddBehavior(typeof(IPipelineBehavior<,>), typeof(MetricsBehavior<,>));
});
public class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, Result<TResponse>>
where TRequest : IRequest<Result<TResponse>>
{
public async Task<Result<TResponse>> Handle(TRequest request, RequestHandlerDelegate<Result<TResponse>> next, CancellationToken cancellationToken)
{
if (!validators.Any())
{
return await next();
}
var context = new ValidationContext<TRequest>(request);
var validationResults = await Task.WhenAll(validators.Select(v => v.ValidateAsync(context, cancellationToken)));
var failures = validationResults
.Where(r => r.Errors.Count != 0)
.SelectMany(r => r.Errors)
.ToList();
if (failures.Count != 0)
{
return new Result<TResponse>(new ValidationException(failures));
}
return await next();
}
}
您可能应该将班级的签名更改为如下所示:
public class ValidationPreProcessor<TRequest> : IRequestPreProcessor<TRequest>{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public ValidationPreProcessor(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public async Task Process(TRequest request, CancellationToken cancellationToken)
{
var context = new ValidationContext<TRequest>(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Any())
{
throw new ValidationException(failures);
}
} }
至于如何注册
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddMediatR(typeof(Startup));
services.AddValidatorsFromAssemblyContaining<Startup>();
// Register pipeline behaviors
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(LoggingBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(AuthorizationBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(PerformanceBehavior<,>));
services.AddTransient(typeof(IPipelineBehavior<,>), typeof(UnhandledExceptionBehavior<,>));
// Register request pre-processors and post-processors
services.AddTransient(typeof(IRequestPreProcessor<>), typeof(ValidationPreProcessor<>));
services.AddTransient(typeof(IRequestPostProcessor<,>), typeof(LoggingPostProcessor<,>));
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}