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

如何扫描实现泛型接口IProductRetriever<T>的类并注册?

扫描实现泛型接口的类并注册到DI容器的解决方案

问题背景

我负责管理不同类型产品,从各厂商API拉取产品信息。因为产品有通用属性,定义了泛型类Product<T>;为统一产品信息获取逻辑,创建了泛型接口IProductRetriever<TProductInfo>,各厂商对应的ProductRetriever类实现该接口,手动调用功能正常。

之前用非泛型接口时,能扫描程序集把ProductRetriever注册到DI容器,但改成泛型接口后,扫描代码里的x.GetInterface(nameof(IProductRetriever<>))部分报错,需要解决怎么扫描实现这个泛型接口的类并完成DI注册。

错误的筛选代码片段:

.Where(x => x is { IsAbstract: false, IsClass: true } && x.GetInterface(nameof(IProductRetriever<>)) == typeof(IProductRetriever<>))

问题原因

泛型接口的类型匹配不能直接用GetInterface加泛型名称的方式,因为GetInterface(nameof(IProductRetriever<>))返回的是构造好的泛型接口类型(比如IProductRetriever<SpecificInfo>),而typeof(IProductRetriever<>)是未构造的泛型接口定义,两者无法直接相等。

解决步骤

1. 修正筛选逻辑

修改代码,检查类是否实现了IProductRetriever<>的泛型定义:

.Where(x => x is { IsAbstract: false, IsClass: true } && 
            x.GetInterfaces()
             .Any(i => i.IsGenericType && 
                       i.GetGenericTypeDefinition() == typeof(IProductRetriever<>)))

逻辑说明:

  • GetInterfaces()获取类实现的所有接口
  • IsGenericType判断当前接口是否为泛型类型
  • GetGenericTypeDefinition()提取泛型接口的原始定义(未构造的IProductRetriever<>),再和目标类型对比

2. 完成DI注册

筛选出符合条件的类后,为每个实现类匹配对应的泛型接口并注册:

var assembly = Assembly.GetExecutingAssembly(); // 可替换为指定要扫描的程序集
var retrieverTypes = assembly.GetTypes()
    .Where(x => x is { IsAbstract: false, IsClass: true } && 
                x.GetInterfaces()
                 .Any(i => i.IsGenericType && 
                           i.GetGenericTypeDefinition() == typeof(IProductRetriever<>)));

foreach (var type in retrieverTypes)
{
    // 获取类实现的IProductRetriever<>接口
    var interfaceType = type.GetInterfaces()
        .First(i => i.IsGenericType && 
                    i.GetGenericTypeDefinition() == typeof(IProductRetriever<>));
    
    // 按需注册为瞬时/作用域/单例
    services.AddTransient(interfaceType, type);
}

3. 简化写法(可选)

如果使用第三方DI扩展库(如Scrutor、Autofac),可以更简洁完成扫描:
以Scrutor为例:

services.Scan(scan => scan
    .FromAssemblyOf<AnyProductRetriever>() // 指定包含实现类的程序集
    .AddClasses(classes => classes.Where(type => 
        type.GetInterfaces()
            .Any(i => i.IsGenericType && 
                      i.GetGenericTypeDefinition() == typeof(IProductRetriever<>))))
    .AsImplementedInterfaces()
    .WithTransientLifetime());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 00:53:14