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

.NET 9中MediatR三泛型ValidationBehavior注册报错的解决方法

解决方案

问题根源很明确:MediatR的AddOpenBehavior要求实现类的泛型参数数量必须和IPipelineBehavior<,>的2个参数完全匹配,而你的ValidationBehavior<,,>多了一个T3泛型参数,导致注册时类型不匹配。

下面提供两种可行的解决方式:

方式一:重构Behavior,移除多余的泛型参数

因为T2本身就是Outcome<T3>,可以通过T2的约束直接推导T3,不需要显式声明第三个泛型参数。修改后的代码如下:

public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse> 
    where TRequest : IRequest<TResponse> 
    where TResponse : Outcome<object>, new()
{
    private readonly IEnumerable<IValidator<TRequest>> _validators;

    public ValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
    {
        _validators = validators;
    }

    public Task<TResponse> Handle(TRequest request, RequestHandlerDelegate<TResponse> next, CancellationToken cancellationToken)
    {
        var errors = _validators
            .Select(v => v.Validate(request))
            .SelectMany(r => r.Errors)
            .Where(e => e != null)
            .Select(e => new Error(e.PropertyName, e.ErrorMessage))
            .ToList();

        if (errors.Any())
        {
            // 若要更精准匹配T3类型,可通过反射获取Outcome的泛型参数
            var outcomeType = typeof(TResponse);
            var t3Type = outcomeType.GetGenericArguments()[0];
            var payloadType = typeof(Payload<>).MakeGenericType(t3Type);
            var payload = Activator.CreateInstance(payloadType, errors);

            var outcome = new TResponse
            {
                Status = Status.Invalid,
                Payload = payload as dynamic // 或定义IPayload统一接口避免dynamic
            };
            
            return Task.FromResult(outcome);
        }

        return next();
    }
}

注册方式保持不变,现在Behavior的泛型参数数量和接口一致:

builder.Services.AddMediatR(x => { 
    x.RegisterServicesFromAssemblyContaining<Program>();
    x.AddOpenBehavior(typeof(ValidationBehavior<,>));
}).AddBehaviors();

方式二:手动注册开放泛型服务,绕过AddOpenBehavior

如果不想修改Behavior的泛型结构,可以直接向DI容器手动注册开放泛型服务,让容器自行处理泛型参数的推导:

builder.Services.AddMediatR(x => { 
    x.RegisterServicesFromAssemblyContaining<Program>();
}).AddBehaviors();

// 手动注册你的3参数Behavior到2参数接口
builder.Services.AddTransient(
    typeof(IPipelineBehavior<,>),
    typeof(ValidationBehavior<,,>)
);

这种方式依赖DI容器(比如MS.DI)的泛型推导能力,只要TResponse的约束Outcome<T3>能让容器正确识别T3的类型,就能正常工作。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 06:36:22