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

Phi*_*tle 10 c# configuration .net-core asp.net-core

使用.NET Core Microsoft.Extensions.Configuration 是否可以将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);
   }
}
Run Code Online (Sandbox Code Playgroud)

Tho*_*mas 19

错误在您的输入定义中.该示例将键"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();
Run Code Online (Sandbox Code Playgroud)

如果使用JSON文件(此处另外调用AddJsonFile),也会发生冒号键重复方案...

{
  "mySecondArray":  [1, 2, 3]
}
Run Code Online (Sandbox Code Playgroud)

生成的组合配置将包含按照上面内存使用所示的相同模式的键:

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]}
Run Code Online (Sandbox Code Playgroud)

配置系统与JSON/INI/XML/...等存储格式无关,实际上只是一个字符串 - >字符串字典,冒号构成了密钥中的层次结构.

然后,绑定能够按约定解释某些层次结构,因此也绑定数组,集合,对象和字典.有趣的是,对于数组,它并不关心冒号后面的数字,而只是迭代配置部分的子节点(这里是"数组")并获取子节点的值.该分拣再次孩子,需要的数量考虑,而且排序字符串作为第二个选项(OrdinalIgnoreCase).

  • 您也可以对非值类型使用相同的技术,只需将属性附加到键即可。因此,如果您的类包含 Id 和 Name,那么您将有两个关键条目:“Array:0:Id”和“Array:0:Name”。(在努力使用 JSON 字符串作为值并返回 null 后了解到)。 (2认同)

cod*_*ion 8

随着最近对 C# 语言的添加,使用更新的语法更清晰:

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

Run Code Online (Sandbox Code Playgroud)

  • 添加后,它应该如下所示:`["Array:0"] = "1", ...`。 (2认同)

ade*_*lin 5

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

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

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

appsettings.json:

{
  "ExampleOption": {
     "Array": [1,2,3]
  }
}
Run Code Online (Sandbox Code Playgroud)

ConfigureServices:

public void ConfigureServices(IServiceCollection services)
{
    services.Configure<ExampleOption>(Configuration.GetSection("ExampleOption"));
}
Run Code Online (Sandbox Code Playgroud)