如何通过foreach为MS DI自动注册Func类型依赖?
批量注册Func到MS DI容器的实现方案
假设你已经通过反射拿到了需要处理的ViewModel类型集合(比如IEnumerable<Type> viewModelTypes),可以通过以下方式批量注册对应的Func<T>:
核心思路
通过反射构造Func<T>泛型类型,再利用表达式树创建工厂委托,最后动态调用DI的注册方法完成批量注册。
实现代码
// 先获取AddSingleton的泛型方法定义(如果是Scoped/Transient,替换成对应的方法名) var addSingletonMethod = typeof(ServiceCollectionServiceExtensions) .GetMethod(nameof(ServiceCollectionServiceExtensions.AddSingleton), new[] { typeof(IServiceCollection), typeof(Func<IServiceProvider, object>) }); foreach (var type in viewModelTypes) { // 构造要注册的Func<T>泛型类型 var funcType = typeof(Func<>).MakeGenericType(type); // 创建工厂委托:s => () => s.GetRequiredService<T>() var factoryDelegate = CreateFuncFactory(type); // 调用泛版的AddSingleton完成注册 var genericRegisterMethod = addSingletonMethod.MakeGenericMethod(funcType); genericRegisterMethod.Invoke(null, new object[] { services, factoryDelegate }); } // 辅助方法:构建对应的工厂委托 private static Func<IServiceProvider, object> CreateFuncFactory(Type targetType) { // 用表达式树构建委托逻辑 var serviceProviderParam = Expression.Parameter(typeof(IServiceProvider), "s"); // 构建s.GetRequiredService<T>()的调用表达式 var getServiceCall = Expression.Call( typeof(ServiceProviderServiceExtensions), nameof(ServiceProviderServiceExtensions.GetRequiredService), new[] { targetType }, serviceProviderParam); // 构建内部无参lambda:() => GetRequiredService<T>() var innerLambda = Expression.Lambda(getServiceCall, Array.Empty<ParameterExpression>()); // 构建外部lambda:s => innerLambda(转换为object兼容委托) var outerLambda = Expression.Lambda<Func<IServiceProvider, object>>( Expression.Convert(innerLambda, typeof(object)), serviceProviderParam); return outerLambda.Compile(); }
注意事项
- 确保所有ViewModel已经提前注册到DI容器中(你提到已能自动注册这些类型,满足前提)
- 如果需要注册
Scoped或Transient的Func<T>,只需将AddSingleton替换为AddScoped或AddTransient,对应的方法定义获取逻辑保持一致 - 表达式树的方式比直接用反射创建委托性能更优,且逻辑更清晰
内容的提问来源于stack exchange,提问作者Istvan Heckl
相关产品推荐
相关产品推荐

