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

C#中如何动态向services.AddHostedService<T>传入泛型参数T?反射调用AddHostedService扩展方法失败的解决方案

解决方案:动态调用泛型扩展方法AddHostedService

你遇到的问题核心在于扩展方法本质是静态类中的静态方法,而非IServiceCollection的实例方法。直接通过typeof(IServiceCollection).GetMethod找不到目标方法,必须从定义它的静态类ServiceCollectionHostedServiceExtensions中获取。

正确的实现方式

我们需要从Microsoft.Extensions.DependencyInjection.ServiceCollectionHostedServiceExtensions类中获取泛型的AddHostedService方法,再通过反射动态指定泛型参数并调用。修改后的AddHostedServices方法如下:

private void AddHostedServices(IServiceCollection services)
{
    HostedServiceSettings settings = Configure<HostedServiceSettings>(services, "HostedServices");
    foreach (PropertyInfo property in typeof(HostedServiceSettings).GetProperties())
    {
        StateOfUse stateOfUse = (StateOfUse)property.GetValue(settings);
        if (stateOfUse.IsActive())
        {
            string hostedServiceName = $"PraxedoIntegration.{property.Name}HostedService";
            Type hostedServiceType = Type.GetType(hostedServiceName);
            if (hostedServiceType == null)
            {
                // 可根据需求添加日志或异常处理,避免类型找不到导致崩溃
                continue;
            }

            // 从静态扩展类中获取泛型方法AddHostedService<T>
            MethodInfo addHostedServiceMethod = typeof(ServiceCollectionHostedServiceExtensions)
                .GetMethod(nameof(ServiceCollectionHostedServiceExtensions.AddHostedService), 
                    new[] { typeof(IServiceCollection) });
            
            // 动态指定泛型参数
            MethodInfo genericMethod = addHostedServiceMethod.MakeGenericMethod(hostedServiceType);
            
            // 调用扩展方法:静态方法第一个参数传null,扩展方法的目标实例(services)作为参数传入
            genericMethod.Invoke(null, new object[] { services });
        }
    }
}

关键细节说明

  1. 扩展方法的获取逻辑:扩展方法定义在ServiceCollectionHostedServiceExtensions静态类中,必须通过该类的Type对象来检索方法,而非IServiceCollection的Type。
  2. Invoke参数规则:静态方法调用时第一个参数传null;扩展方法的第一个参数(即IServiceCollection实例)需要作为Invoke的参数数组的第一个元素传入。
  3. 类型安全校验:添加了hostedServiceType == null的判断,处理类型名称拼写错误等场景,提升代码健壮性。

简洁替代方案(可选)

如果觉得反射调用扩展方法过于繁琐,也可以直接将托管服务注册为IHostedService的单例,效果与AddHostedService<T>完全一致:

services.AddSingleton<IHostedService>(Activator.CreateInstance(hostedServiceType) as IHostedService);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 09:52:33