ASP.NET Core 6中如何在Program.cs正确调用已注册服务配置其他服务
正确解决依赖注入中用一个服务配置另一个服务的问题
你之前用BuildServiceProvider创建临时服务提供器的方式会触发重复服务警告,原因是这个临时容器和应用最终使用的容器是独立的,会导致服务被实例化两次,同时还可能带来配置不一致、死锁等风险。以下是无需修改第二个服务的正确解决方案:
核心思路
利用依赖注入的延迟解析能力,在注册第二个服务时,通过最终的服务提供器(而非临时容器)解析第一个服务,获取配置所需的值后再实例化第二个服务。
方案1:异步注册(适用于异步获取配置的场景)
如果GetPasswordAsync是异步方法,推荐使用AddSingletonAsync(.NET 6+支持)来处理异步逻辑:
builder.Services.AddFirstService(); // 注册第二个服务时,通过服务提供器解析第一个服务并获取密码 builder.Services.AddSingletonAsync<ISecondService>(async serviceProvider => { var firstService = serviceProvider.GetRequiredService<IFirstService>(); var password = await firstService.GetPasswordAsync(); // 实例化第二个服务,传入获取到的密码 return new SecondService(password); });
方案2:同步注册(仅当异步方法可安全同步调用时使用)
如果必须同步处理,可使用GetAwaiter().GetResult(),但要注意避免死锁风险(比如在ASP.NET Core环境中需确保上下文兼容):
builder.Services.AddFirstService(); builder.Services.AddSingleton<ISecondService>(serviceProvider => { var firstService = serviceProvider.GetRequiredService<IFirstService>(); var password = firstService.GetPasswordAsync().GetAwaiter().GetResult(); return new SecondService(password); });
扩展方法适配(如果AddSecondService是自定义扩展)
如果AddSecondService是你自己写的扩展方法,可以修改它来支持延迟解析(无需修改SecondService类):
public static IServiceCollection AddSecondService(this IServiceCollection services) { services.AddSingletonAsync<ISecondService>(async sp => { var firstService = sp.GetRequiredService<IFirstService>(); var password = await firstService.GetPasswordAsync(); return new SecondService(password); }); return services; }
之后直接调用builder.Services.AddSecondService()即可。
为什么原来的方法不可取
- 创建临时
ServiceProvider会导致服务被重复注册和实例化,浪费资源且可能出现状态不一致 - 临时容器无法感知后续对
builder.Services的配置修改,可能导致使用过时的服务配置
内容的提问来源于stack exchange,提问作者Gargoyle
相关产品推荐
相关产品推荐

