.NET Core 3.x中IConfiguration注入及密钥读取问题咨询
问题场景
有一个依赖IConfiguration的类:
public class NeedsConfiguration : INeedsConfiguration { private readonly IConfiguration config; public NeedsConfiguration(IConfiguration config) { this.config = config; } // 类的业务逻辑此处省略 }
该类默认可以读取环境变量、appsettings等配置项,但在调用services.AddAzureKeyVault("key-vault-url")后,类内部的config仍然无法读取Azure密钥保管库中的密钥。
已尝试的可行方案:
- 将Startup.cs中的
Configuration注册为单例:services.AddSingleton<IConfiguration>(Configuration); - 手动注册依赖
IConfiguration的类:services.AddScoped<INeedsConfiguration>(x => new NeedsConfiguration(Configuration));
其中第二种方法手动工作量大,第一种更优,但模板默认未包含该配置。
疑问解答
1. .NET Core 3.x中IConfiguration注入的官方推荐方式
在.NET Core中,IConfiguration默认就是以单例形式被框架自动注册到DI容器的,不需要手动调用services.AddSingleton<IConfiguration>(Configuration)。模板里没有显式注册,是因为应用启动阶段框架已经完成了这个过程。
你遇到的手动注册才能读取Key Vault密钥的情况,本质是配置源添加顺序和服务解析时机不匹配导致的。正确的流程应该是:
- 在
Program.cs中构建配置时,提前添加Azure密钥保管库配置源,确保所有配置源加载完成后再初始化DI容器:
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { var builtConfig = config.Build(); // 添加Azure密钥保管库配置源 config.AddAzureKeyVault( new Uri(builtConfig["KeyVaultUrl"]), new DefaultAzureCredential()); }) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseStartup<Startup>(); });
- 直接通过常规方式注册依赖
IConfiguration的服务即可,无需额外处理IConfiguration的注册:
services.AddScoped<INeedsConfiguration, NeedsConfiguration>();
2. 配置读取部分生效的原因
环境变量、appsettings等配置源是CreateDefaultBuilder在应用启动初期就默认加载的,而Azure密钥保管库的配置源是你在ConfigureServices阶段才添加的。如果NeedsConfiguration类在Key Vault配置源添加前就被DI容器实例化,它拿到的IConfiguration实例还没有包含Key Vault的配置数据,自然读不到密钥;但此时环境变量、appsettings已经加载完成,所以能正常读取。
另外,如果你手动注册IConfiguration单例时用的是Startup构造函数中提前构建的Configuration实例(未包含Key Vault配置源),也会出现读不到密钥的情况——必须确保DI容器提供的IConfiguration是包含所有配置源的最终实例。
核心问题是配置源添加顺序与服务解析时机不匹配,而非IConfiguration的注册方式问题。
内容的提问来源于stack exchange,提问作者Jakob Busk Sørensen

