IConfiguration.Get<>() 无法检索那些属性为空数组的元素
我正在尝试从我的 appsettings.json 导入我的 ServerProcessConfig[]。如果数组中有一个元素在 Dependencies 上是一个空数组,它就无法导入整个配置对象。
尝试了是否允许空值的两种情况。
using Microsoft.Extensions.Configuration;
var configuration = new ConfigurationBuilder()
.SetBasePath(AppContext.BaseDirectory)
.AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
.Build();
var servers = configuration
.GetSection("Servers")
.Get<List<ServerProcessConfig>>()!;
Console.WriteLine(servers.Count);
public sealed record ServerProcessConfig(
int Id,
int[]? Dependencies);
在 Servers 数组中的以下元素被跳过,因此检索到的服务器配置数量为1。尝试了空数组的情况,并尝试移除该属性。
appsettings.json
{"Servers": [
{
"Id": 1,
"Dependencies": []
},
{
"Id": 2,
"Dependencies": [1]
},
]}
这有效,元素出现在 servers[] 中,servers 的长度为2。
{
"Id": 1,
"Dependencies": [0]
}
解决方案
我能够在.NET 10中重现你的问题,失败的演示fiddle #1可以在这里看到 这里。问题似乎出在对具有参数化构造函数的类型进行绑定时,因为我也能够在等效的带参数的类中重现完全相同的行为:
public sealed class ServerProcessConfig // Also does not bind when Dependencies has Length zero.
{
public ServerProcessConfig(int Id, int[]? Dependencies) => (this.Id, this.Dependencies) = (Id, Dependencies);
public int Id { get; }
public int[]? Dependencies { get; }
}
请在这里查看失败的演示fiddle #2:这里。
作为一种变通方法,我建议用 public required ... { get; init; } 属性替换参数化属性,像这样:
public sealed record ServerProcessConfig
{
public required int Id { get; init; }
public required int[]? Dependencies { get; init; }
}
使用这个版本的 ServerProcessConfig,设置数组绑定成功。(具有相同属性的类也可以工作。)
请在这里查看可运行的演示fiddle #3:这里。
并且,正如 Ivan Petrov 在评论中提到的,添加一个无参构造函数也能解决这个问题:
public sealed record ServerProcessConfig(
int Id,
int[]? Dependencies)
{
public ServerProcessConfig() : this(-1, null) { }
}
采用这种方式,位置属性不再是必需的,因此下面的代码现在可以编译:
var test1 = new ServerProcessConfig { Id = 101 }; // Note - still seems to compile even without setting Dependencies
可运行的fiddle #4请在这里:这里。
你可以考虑向微软报告这个问题;一般来说,绑定具有带有数组值参数的参数化构造函数的类型是受支持的,因此在数组长度为零时绑定失败就显得奇怪。
站内所有文章版权归属LeftHeroAI导航站,无授权禁止任何主体转载、抄袭、复制内容,亦不得私自架设镜像站点。一经侵权,本站将通过法律途径追责。