从 .NET 8 开始, ConfigurationBinder 以无提示方式跳过数组和列表元素,其值无法转换为目标类型。 以前,失败的元素保留为 null 占位符,生成的集合保留的长度与配置源中的元素数相同。
已引入的版本
.NET 8
以前的行为
以前,当通过Get<T>(IConfiguration)或Bind(IConfiguration, Object)绑定数组或列表属性时,如果无法将元素的值转换为目标类型,该元素将在结果中作为null占位符保留。 集合长度与配置中的元素数匹配。
// Configuration source, for example, appsettings.json:
// "Items": [
// { "Name": "A", "Interval": 10 },
// { "Name": "B", "Interval": "a" } <-- invalid int
// ]
var settings = configuration.GetSection("Items").Get<MyItem[]>();
// .NET 6/7 result:
// settings.Length == 2
// settings[0] = { Name = "A", Interval = 10 }
// settings[1] = null (conversion failed, placeholder preserved)
新行为
从 .NET 8 开始,将无提示跳过失败类型转换的元素。 生成的集合仅包含已成功绑定的元素,其长度比配置源中的条目数短。
var settings = configuration.GetSection("Items").Get<MyItem[]>();
// .NET 8+ result:
// settings.Length == 1
// settings[0] = { Name = "A", Interval = 10 }
破坏性变更的类型
此更改为行为更改。
更改原因
.NET 8 中对 ConfigurationBinder 的内部实现进行了重构。 现在,绑定器不会预先分配目标数组并在原地绑定元素(在转换失败后留下 null),而是将成功绑定的元素收集到一个临时列表中,然后在最终生成数组前进行处理。
对于值类型(如 int[])而言,以前的行为也存在问题。 对于无效的配置值,绑定器将存储 0,这与合法值 0不可区分。 新行为可避免这种歧义。
建议的操作
在开发过程中启用ErrorOnUnknownConfiguration以立即显示无效的配置值,而不是以无提示方式删除元素:
var settings = configuration.GetSection("Items").Get<MyItem[]>(options => options.ErrorOnUnknownConfiguration = true);从 .NET 8 开始,此选项还会导致 ConfigurationBinder 在无法转换为目标类型时引发 InvalidOperationException 值。 有关详细信息,请参阅 ConfigurationBinder 在值不匹配时抛出异常。
修复无效的配置值。 确保配置源中的所有值都与绑定模型的预期类型匹配。
如果代码依赖于与配置源匹配的元素数,请在绑定后验证集合长度。
如果需要正常处理不可转换的值并保留所有数组条目,请使用带手动分析的字符串属性。
受影响的 API
- Microsoft.Extensions.Configuration.ConfigurationBinder.Get<T>(IConfiguration)
- Microsoft.Extensions.Configuration.ConfigurationBinder.Get<T>(IConfiguration, Action<BinderOptions>)
- Microsoft.Extensions.Configuration.ConfigurationBinder.Bind(IConfiguration, Object)
- Microsoft.Extensions.Configuration.ConfigurationBinder.Bind(IConfiguration, Object, Action<BinderOptions>)