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

使用Scrutor注册开放泛型时构建ServiceProvider失败的原因分析

Scrutor泛型服务注册异常解析

一、原代码正常运行的原因

原代码的Scrutor扫描逻辑仅做了两件事:

  1. 筛选出所有可赋值给IInterface<>的类,这里Concrete<TOther>因继承AbstractClass<string>(实现了IInterface<string>)被选中。
  2. 通过.AsSelf()将类本身注册为服务。

此时DI容器只需要处理Concrete<TOther>这个开放泛型类型的注册——当后续请求Concrete<SomeSpecificType>时,容器可以通过传入具体的SomeSpecificType作为TOther的参数来实例化对象,完全符合泛型服务注册规则,因此运行正常。

二、取消注释后抛出ArgumentException的原因

取消注释的代码行是自定义服务类型映射:

.As(type => type.GetInterfaces().Where(v => v.IsGenericType && v.GetGenericArguments().Length == 1).ToArray())

它的作用是让Scrutor将类实现的所有单参数泛型接口都注册为服务。

对于Concrete<TOther>来说,它继承的AbstractClass<string>实现了IInterface<string>(封闭泛型接口,已指定类型参数为string)。这行代码会把IInterface<string>作为服务类型,Concrete<TOther>作为实现类型注册到容器中。

问题的核心矛盾:

  • IInterface<string>是封闭泛型服务(类型参数已固定)
  • Concrete<TOther>是开放泛型实现(存在未绑定的类型参数TOther)

DI容器无法用开放泛型类型去实例化封闭泛型服务——当你请求IInterface<string>时,容器不知道该为TOther传入什么具体类型来创建Concrete<TOther>的实例,因此抛出异常:无法为服务类型“IInterface[System.String]”实例化实现类型“Concrete[TOther]”。

三、修复思路(可选)

如果想正确注册泛型接口,需要保证服务类型和实现类型的泛型参数匹配。比如:

  • 调整实现类定义,让Concrete<T>直接继承AbstractClass<T>,使泛型参数对应;
  • 或者修改接口筛选逻辑,排除掉那些类型参数不匹配的封闭泛型接口。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 16:10:24