You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

替换为LangExt Result<T>后MediatR的ValidationBehavior未触发

问题

我用LangExt库把所有异常替换成Result<T>后,遇到ValidationBehavior完全不触发的问题。之前当ValidationBehavior的签名是public class ValidationBehavior<TRequest, TResponse>(IEnumerable<IValidator<TRequest>> validators) : IPipelineBehavior<TRequest, TResponse> where TRequest : IRequest<TResponse>时能正常触发,现在需要调整注册方式让它重新生效,而且不想手动指定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<>));
});

ValidationBehavior实现代码

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();
    }
}
解决方案

问题根源是你的MediatR注册代码和ValidationBehavior的泛型约束不匹配:现在的Behavior实现的是IPipelineBehavior<TRequest, Result<TResponse>>(返回类型固定为Result<TResponse>),但注册时还是用了通用的IPipelineBehavior<,>,导致MediatR无法将它匹配到对应的请求上。

修改注册代码中的AddBehavior部分,把ValidationBehavior的注册改成匹配其泛型约束的形式:

builder.Services.AddValidatorsFromAssemblyContaining<Program>();
builder.Services.AddMediatR(configure =>
{
    configure.RegisterServicesFromAssemblyContaining<Program>();
    configure.AddRequestPreProcessor(typeof(IRequestPreProcessor<>), typeof(LoggingBehavior<>));
    // 调整ValidationBehavior的注册,匹配它实现的IPipelineBehavior<TRequest, Result<TResponse>>开放泛型
    configure.AddBehavior(typeof(IPipelineBehavior<, Result<>>), typeof(ValidationBehavior<,>));
    configure.AddBehavior(typeof(IPipelineBehavior<,>), typeof(MetricsBehavior<>));
});

同时,确保你的请求类都实现了IRequest<Result<T>>接口(比如public class MyRequest : IRequest<Result<MyResponse>>),这样MediatR才能把ValidationBehavior关联到这些请求上。

另外,AddValidatorsFromAssemblyContaining<Program>()已经会自动扫描并注册程序集中所有继承自AbstractValidator<T>的验证器,所以不需要手动指定任何验证器类,只要请求对应的验证器存在,就会被注入到ValidationBehavior的validators参数中。

内容的提问来源于stack exchange,提问作者nop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:05:06