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

如何通过反射在Microsoft.Extensions.Hosting中注册泛型类型?

反射注册泛型服务的问题解决方法

问题根源

你当前的反射代码失败有两个核心原因:

  1. 泛型类型名称格式问题:泛型类/接口的Name属性会带有`1后缀(比如Common<T>的Name是Common1,ICommon是ICommon1),你用$"I{name}"的匹配逻辑根本找不到对应的接口。
  2. 未区分开放泛型定义:注册泛型服务时,必须注册开放泛型类型(也就是typeof(ICommon<>)这种不带具体类型参数的泛型定义),你的代码没做这个判断,直接注册会触发异常。

可行的反射注册实现

下面是修正后的代码,能正确识别并注册泛型服务,同时兼容非泛型服务的注册:

var types = assembly.GetTypes().Where(t => !t.IsInterface && !t.IsAbstract);
foreach (var type in types)
{
    Type interfaceType = null;
    
    // 处理泛型类
    if (type.IsGenericTypeDefinition)
    {
        // 去掉名称里的泛型参数标记(`1`部分)
        var genericTypeName = type.Name.Split('`')[0];
        // 匹配对应的泛型接口定义:接口是泛型定义,且名称为I+泛型类名
        interfaceType = type.GetInterfaces()
            .Where(i => i.IsGenericTypeDefinition)
            .FirstOrDefault(i => i.Name.Split('`')[0] == $"I{genericTypeName}");
    }
    // 处理非泛型类
    else
    {
        var name = type.Name;
        interfaceType = type.GetInterfaces().FirstOrDefault(p => p.Name.Equals($"I{name}"));
    }

    if (interfaceType == null)
    {
        continue;
    }

    // 根据需求替换生命周期:Scoped/Singleton/Transient
    services.TryAddScoped(interfaceType, type);
}

代码说明

  • 通过IsGenericTypeDefinition判断当前类型是否为泛型定义,分开处理泛型和非泛型逻辑。
  • 对于泛型类型,分割名称中的`符号去掉泛型参数标记,再匹配对应的I开头泛型接口。
  • 注册时使用和手动注册一致的生命周期(示例用TryAddScoped,可按需替换为其他生命周期)。

验证

用这段代码注册你的ICommon<T>和Common<T>,效果和手动写services.TryAddScoped(typeof(ICommon<>), typeof(Common<>))完全一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.14 11:52:34