基于HostBuilder DI容器的自定义配置提供者初始化含自定义对象数组的Options对象失败问题求助
解决自定义配置提供者初始化包含自定义对象数组的Options问题
我明白你遇到的困境了——用自定义配置提供者绑定包含自定义对象数组的Options时,原始类型能正常工作,但自定义类型的数组就是没被初始化。这其实是因为.NET配置绑定系统在处理数组时,需要明确知道数组的长度,或者能识别出这是一个数组结构,而你的当前代码缺少了关键的标记。
问题原因
当你只添加FooOptions:Bars:{i}:Blah这样的键时,配置系统无法确定Bars是一个数组(它可能会被当成一个普通的嵌套配置节),所以不会自动创建Bar对象的数组并填充数据。
解决方案
你需要在配置数据中添加数组的长度标记,或者确保配置系统能识别出数组的结构。最可靠的方式是添加Count键来指定数组长度,具体修改如下:
1. 修改自定义配置提供者的CreateConfiguration方法
在生成配置字典时,添加{fooOptionsName}:Bars:Count项,告诉配置系统数组的长度:
public IDictionary<string, string> CreateConfiguration() { var configuration = new Dictionary<string, string>(); var fooOptionsName = nameof(FooOptions); var bars = new Bar[] { new Bar() { Blah = "A" }, new Bar() { Blah = "B" } }; // 添加数组长度标记,让配置系统识别这是一个数组 configuration.Add($"{fooOptionsName}:Bars:Count", bars.Length.ToString()); for (var i = 0; i < bars.Length; i++) { configuration.Add($"{fooOptionsName}:Bars:{i}:Blah", bars[i].Blah); } return configuration; }
2. 确保配置源正确注册
你还需要创建对应的配置源类,让HostBuilder能加载你的自定义提供者:
public class FooConfigurationSource : IConfigurationSource { public IConfigurationProvider Build(IConfigurationBuilder builder) { return new FooConfigurationProvider(); } }
然后在HostBuilder中注册这个配置源:
var host = Host.CreateDefaultBuilder(args) .ConfigureAppConfiguration((context, config) => { // 添加自定义配置源 config.Add(new FooConfigurationSource()); }) .ConfigureServices((context, services) => { // 绑定FooOptions到配置节 services.Configure<FooOptions>(context.Configuration.GetSection(nameof(FooOptions))); }) .Build();
3. 验证绑定结果
现在当你获取IOptions<FooOptions>时,Bars数组应该会被正确初始化,包含两个Bar对象,它们的Blah属性分别是"A"和"B":
var fooOptions = host.Services.GetRequiredService<IOptions<FooOptions>>().Value; // fooOptions.Bars[0].Blah 应为 "A" // fooOptions.Bars[1].Blah 应为 "B"
额外说明
除了添加Count键,你也可以通过确保数组索引从0开始连续无空缺,让配置系统自动识别数组,但显式添加Count是更稳妥的方式,尤其是当数组长度动态变化或者你想明确指定长度时。
内容的提问来源于stack exchange,提问作者Petr M
相关产品推荐
相关产品推荐

