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 }); } } }
关键细节说明
- 扩展方法的获取逻辑:扩展方法定义在
ServiceCollectionHostedServiceExtensions静态类中,必须通过该类的Type对象来检索方法,而非IServiceCollection的Type。 - Invoke参数规则:静态方法调用时第一个参数传
null;扩展方法的第一个参数(即IServiceCollection实例)需要作为Invoke的参数数组的第一个元素传入。 - 类型安全校验:添加了
hostedServiceType == null的判断,处理类型名称拼写错误等场景,提升代码健壮性。
简洁替代方案(可选)
如果觉得反射调用扩展方法过于繁琐,也可以直接将托管服务注册为IHostedService的单例,效果与AddHostedService<T>完全一致:
services.AddSingleton<IHostedService>(Activator.CreateInstance(hostedServiceType) as IHostedService);
内容的提问来源于stack exchange,提问作者Brian Kessler
相关产品推荐
相关产品推荐

