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

.NET Core注册泛型IOrder<T>实现后能否通过GetServices获取所有服务

问题解答

能否直接通过GetServices API实现?

直接调用GetServices(typeof(IOrder<>))无法获得你注册的所有IOrder<Chair>、IOrder<Table>实例,原因是你注册的是闭合构造泛型类型(已经指定了具体泛型参数的泛型类型),而IOrder<>是开放泛型定义,二者在DI容器中属于不同的服务类型,默认没有关联,因此无法直接通过开放泛型定义批量获取所有闭合泛型实现。
如果使用支持开放泛型批量解析的第三方DI容器(如Autofac),可以直接注册开放泛型services.AddSingleton(typeof(IOrder<>), typeof(FurnitureOrder<>)),之后直接解析IEnumerable<IOrder<>>即可获取所有泛型实现,但.NET官方自带DI不支持该特性。


实现方案

方案1:无需修改现有接口定义,通过反射遍历获取

如果不想调整现有接口结构,可以通过遍历所有需要的泛型参数类型,动态构造闭合泛型类型后逐个从容器获取实例:

  1. 首先定义标记接口(可选,用于快速筛选所有可用的泛型参数类型,也可以手动维护T类型列表省略该步骤):
// 所有IOrder<T>的T参数都实现该标记接口
public interface IOrderItem { }
public class Chair : IOrderItem { }
public class Table : IOrderItem { }
  1. 后台服务中批量获取实例:
public class OrderBackgroundService : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public OrderBackgroundService(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // 扫描程序集获取所有实现IOrderItem的类型
        var orderItemTypes = AppDomain.CurrentDomain.GetAssemblies()
            .SelectMany(a => a.GetTypes())
            .Where(t => typeof(IOrderItem).IsAssignableFrom(t) && !t.IsInterface && !t.IsAbstract);

        foreach (var itemType in orderItemTypes)
        {
            // 动态构造闭合泛型类型 IOrder<ItemType>
            var closedOrderType = typeof(IOrder<>).MakeGenericType(itemType);
            // 从容器获取对应服务
            var orderService = _serviceProvider.GetService(closedOrderType);
            if (orderService != null)
            {
                // 这里可以通过反射调用orderService的方法,或者转换为动态类型执行
                await (Task)closedOrderType.GetMethod("你的业务方法名")?.Invoke(orderService, new object[] { stoppingToken });
            }
        }
    }
}

方案2:调整接口设计,新增非泛型基接口(更推荐)

该方案复杂度更低,运行效率更高,也不需要依赖反射:

  1. 新增非泛型基接口:
public interface IOrder
{
    // 暴露对应的泛型参数类型
    Type OrderItemType { get; }
    // 统一的任务执行入口
    Task ExecuteAsync(CancellationToken cancellationToken);
}

// 原泛型接口继承非泛型基接口
public interface IOrder<T> : IOrder { }

// 实现类中实现基接口属性
public class FurnitureOrder<T> : IOrder<T>
{
    public Type OrderItemType => typeof(T);

    public Task ExecuteAsync(CancellationToken cancellationToken)
    {
        // 你的业务逻辑
        return Task.CompletedTask;
    }
}
  1. 注册逻辑无需修改,直接批量获取所有实例:
var allOrderServices = serviceProvider.GetServices<IOrder>();
foreach (var order in allOrderServices)
{
    // 直接获取对应的泛型参数类型
    var itemType = order.OrderItemType;
    // 执行任务
    await order.ExecuteAsync(stoppingToken);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 09:39:02