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

Ninject使用约定绑定无法注册MediatR.IRequestHandler<,>怎么解决?

问题核心原因及修复方案

1. 核心问题:逆变绑定解析器仅支持单泛型参数接口

你当前实现的ContravariantBindingResolver只处理了泛型参数数量为1的接口,仅适配INotificationHandler<>这类单泛型参数的接口,而IRequestHandler<,>是双泛型参数的接口,自然无法被正确解析绑定。

2. 修复逆变绑定解析器

需要扩展解析器逻辑,同时兼容单泛型和双泛型参数的逆变接口:

public class ContravariantBindingResolver : NinjectComponent, IBindingResolver
{
    public IEnumerable<IBinding> Resolve(Multimap<Type, IBinding> bindings, Type service)
    {
        if (!service.IsGenericType) 
            return Enumerable.Empty<IBinding>();
        
        var genericTypeDef = service.GetGenericTypeDefinition();
        var genericArgs = service.GetGenericArguments();

        // 适配单泛型参数的逆变接口(INotificationHandler<>等)
        if (genericArgs.Length == 1 
            && genericArgs[0].GenericParameterAttributes.HasFlag(GenericParameterAttributes.Contravariant))
        {
            var arg = genericArgs[0];
            return bindings.Where(kvp => kvp.Key.IsGenericType
                                      && kvp.Key.GetGenericTypeDefinition() == genericTypeDef
                                      && kvp.Key.GetGenericArguments()[0] != arg
                                      && kvp.Key.GetGenericArguments()[0].IsAssignableFrom(arg))
                           .SelectMany(kvp => kvp.Value);
        }

        // 适配双泛型参数的逆变接口(IRequestHandler<,>、IPipelineBehavior<,>等)
        if (genericArgs.Length == 2
            && genericArgs.All(x => x.GenericParameterAttributes.HasFlag(GenericParameterAttributes.Contravariant)))
        {
            var arg1 = genericArgs[0];
            var arg2 = genericArgs[1];
            return bindings.Where(kvp => kvp.Key.IsGenericType
                                      && kvp.Key.GetGenericTypeDefinition() == genericTypeDef
                                      && kvp.Key.GetGenericArguments()[0].IsAssignableFrom(arg1)
                                      && kvp.Key.GetGenericArguments()[1] == arg2)
                           .SelectMany(kvp => kvp.Value);
        }

        return Enumerable.Empty<IBinding>();
    }
}

3. 其他需校验的配置项

  • 确认扫描配置包含嵌套类:你当前的处理程序是嵌套在SupplierInvoice类中的内部类,若扫描时未开启嵌套类识别,绑定可能失效,可调整扫描代码:
Kernel.Bind(services => services.FromThisAssembly()
                                .SelectAllClasses()
                                .IncludingNestedClasses() // 新增这行,包含嵌套类
                                .InheritedFrom(typeof(IRequestHandler<,>))
                                .BindAllInterfaces());
  • 确认依赖包版本匹配:确保你安装的Ninject.Extensions.Conventions、MediatR版本兼容,避免接口签名不匹配导致绑定失败。
  • 手动绑定时排查编译错误:如果手动绑定都无法成功,优先检查ProcessCommand、ProcessedTransaction、IRequestHandler的命名空间是否一致,有没有引用错不同版本的程序集。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 03:06:04