C#依赖注入中AddOptions与Bind绑定后Environments为空问题排查
.NET依赖注入中AddOptions与Bind配置问题排查与解决
问题现象
开发基于依赖注入的控制台应用时,配置DI环节遇到如下差异问题:
- 使用
services.Configure<T>(section)时,注入的IOptions<T>实例不为空,且Environments列表已正常填充配置内容 - 使用
services.AddOptions<T>(sectionKey).Bind(section)时,注入的IOptions<T>实例不为空,但Environments属性为null
代码复现
DI配置代码
public static IHost BuildHost() { var builder = Host.CreateDefaultBuilder() .ConfigureServices((context, services) => { //...... ConfigureSettings<Settings>(nameof(Settings)); //....... void ConfigureSettings<T>(string sectionKey) where T : class, new() { var section = context.Configuration.GetSection(sectionKey); //services.Configure<T>(section); // 此代码可正常工作 services.AddOptions<T>(sectionKey).Bind(section); // 此代码导致Environments为空 } }); return builder.Build(); }
appsettings.json配置
{ "Settings": { "Environments": [ { "EnvironmentName" : "Staging", "BaseUri" : "https://stage.uri.com" }, { "EnvironmentName" : "Development", "BaseUri" : "https://dev.uri.com" } ] } }
绑定类定义
public class Settings { [Required] public List<Environment> Environments { get; set; } } public class Environment { [Required] public string EnvironmentName { get; set; } [Required] public string BaseUri { get; set; } }
问题根源
services.AddOptions<T>(sectionKey)创建的是命名选项,这类选项无法通过IOptions<T>接口直接获取,必须通过IOptionsSnapshot<T>或IOptionsMonitor<T>的Get(sectionKey)方法才能拿到对应命名的配置实例。而services.Configure<T>(section)配置的是默认(无命名)选项,因此IOptions<T>可以正常获取到填充后的完整配置。
解决方案
将配置代码修改为以下形式,配置默认选项即可让IOptions<T>正常获取到完整配置:
services.AddOptions<T>().Bind(section);
内容的提问来源于stack exchange,提问作者pampua84
相关产品推荐
相关产品推荐

