如何在调用BuildServiceProvider之前访问已注册的服务
你现在遇到的核心问题是:ServiceCollection 只是服务注册的存储清单,在调用 BuildServiceProvider() 之前,所有注册的服务都只是配置条目,没有完成实例化,你代码里 services.AddSingleton<ConfigurationStore>() 返回的是 IServiceCollection 类型,根本不是 ConfigurationStore 的实例,自然没办法直接传给 AddInMemoryConfiguration 方法。
有两种可行的实现方案:
方案1:提前手动实例化配置存储(优先推荐)
如果你的 ConfigurationStore 没有其他需要容器注入的依赖,直接提前实例化对象再注册到容器即可,和容器自动创建单例的效果完全一致:
var services = new ServiceCollection(); // 提前手动实例化配置存储对象 var configStoreService = new ConfigurationStore(); // 将现成的实例注册为单例,容器后续会直接复用该实例 services.AddSingleton<ConfigurationStore>(configStoreService); var configuration = new ConfigurationBuilder() .AddInMemoryConfiguration(configStoreService) .Build(); services.AddOptions(); services.Configure<Temp>(configuration.GetSection(typeof(Temp).Name)); services.RegisterOptionsType<Temp>(configuration); _serviceProvider = services.BuildServiceProvider();
方案2:构建临时服务提供器解析实例
如果 ConfigurationStore 本身有其他依赖需要容器解析,可以先构建一个临时的服务提供器拿到实例,再把实例注册回服务集合,避免最终容器生成重复的单例:
var services = new ServiceCollection(); // 先注册ConfigurationStore以及它的所有依赖项 services.AddSingleton<ConfigurationStore>(); // 示例:如果ConfigurationStore依赖其他服务,提前完成注册 services.AddSingleton<IDependencyService, DependencyServiceImpl>(); // 构建临时服务提供器解析实例 using var tempProvider = services.BuildServiceProvider(); var configStoreService = tempProvider.GetRequiredService<ConfigurationStore>(); // 覆盖注册,保证最终容器使用的是同一个实例 services.AddSingleton<ConfigurationStore>(configStoreService); var configuration = new ConfigurationBuilder() .AddInMemoryConfiguration(configStoreService) .Build(); services.AddOptions(); services.Configure<Temp>(configuration.GetSection(typeof(Temp).Name)); services.RegisterOptionsType<Temp>(configuration); _serviceProvider = services.BuildServiceProvider();
注意事项
- 优先选择方案1,性能更高且不会出现多实例冲突问题
- 使用方案2时必须保证
ConfigurationStore的所有依赖在构建临时容器前已经完成注册,否则会解析失败 - 不要在最终服务提供器构建完成后再修改配置,默认配置源都是初始化时读取数据,后续修改不会自动同步到已加载的配置对象
内容的提问来源于stack exchange,提问作者Haha
相关产品推荐
相关产品推荐

