.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
相关产品推荐
相关产品推荐

