.NET Core使用Configuration绑定到具有Array的Options



使用.NET CoreMicrosoft.Extensions.Configuration是否可以将配置绑定到包含数组的对象

ConfigurationBinder有一个方法BindArray,所以我认为它可以工作。

但当我尝试它时,我得到了一个例外:

System.NotSupportedException: ArrayConverter cannot convert from System.String.

这是我精简的代码:

public class Test
{
private class ExampleOption
{ 
public int[] Array {get;set;}
}
[Test]
public void CanBindArray()
{
// ARRANGE
var config =
new ConfigurationBuilder()
.AddInMemoryCollection(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Array", "[1,2,3]")
})
.Build();
var exampleOption= new ExampleOption();
// ACT
config.Bind(complexOptions); // throws exception
// ASSERT
exampleOption.ShouldContain(1);
}
}

错误在您的输入定义中。该示例将键"Array"设置为字符串值"[1,2,3]"(在基于C#的InMemoryCollection中),并假设它是解析的JSON样式。这是错误的。它只是没有被解析。

配置系统中数组值的编码约定是通过重复后面有冒号和索引的键

var config = new ConfigurationBuilder()
.AddInMemoryCollection(new List<KeyValuePair<string, string>>
{
new KeyValuePair<string, string>("Array:0", "1"),
new KeyValuePair<string, string>("Array:1", "2"),
new KeyValuePair<string, string>("Array:2", "3")
})
.Build();

如果使用JSON文件(此处通过对AddJsonFile的额外调用),也会出现冒号键重复方案。。。

{
"mySecondArray":  [1, 2, 3]
}

所得到的组合配置将包含密钥,这些密钥遵循与上面针对内存使用所示的相同模式:

Count = 8
[0]: {[mySecondArray, ]}
[1]: {[mySecondArray:2, 3]}
[2]: {[mySecondArray:1, 2]}
[3]: {[mySecondArray:0, 1]}
[4]: {[Array, ]}
[5]: {[Array:2, 3]}
[6]: {[Array:1, 2]}
[7]: {[Array:0, 1]}

配置系统与JSON/INI/XML/等存储格式无关。。。本质上只是一个字符串->字符串字典,冒号构成键内的层次结构。

然后,Bind能够通过约定来解释某些层次结构,因此还绑定数组、集合、对象和字典。有趣的是,对于数组,它不关心冒号后面的数字,而只是迭代配置部分的子级(此处为"Array")并获取子级的值。再次对子项进行排序时,会考虑数字,但也会将字符串作为第二个选项进行排序(OrdinalIgnoreCase)。

随着C#语言的最新添加,使用较新的语法会更干净:

var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
{ "Array:0", "1" },
{ "Array:1", "2" },
{ "Array:2", "3" },
})
.Build();

或者你可以使用其他新的语法

var config = new ConfigurationBuilder()
.AddInMemoryCollection(new Dictionary<string, string>
{
["Array:0"] = "1",
["Array:1"] = "2",
["Array:2"] = "3",
})
.Build();

您可以使用ConfigureServices方法中的代码配置ExampleOption

public void ConfigureServices(IServiceCollection services)
{
services.Configure<ExampleOption>(myOptions =>
{
myOptions.Array = new int[] { 1, 2, 3 };
});
}

或者如果您想使用json配置文件

appsettings.json:

{
"ExampleOption": {
"Array": [1,2,3]
}
}

ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
services.Configure<ExampleOption>(Configuration.GetSection("ExampleOption"));
}

最新更新