.NET Core 配置管理器读取其中一个键内部有冒号的字典,给出有关该值的奇怪错误消息,这是预期的吗?

.NET Core configuration manager, reading a dictionary where one key has a colon inside, gives an odd error message about the value, is this expected?

以下程序:

using System;
using System.Collections.Generic;
using Microsoft.Extensions.Configuration;

namespace ConsoleApp3
{
    class Program
    {
        static void Main()
        {
            var builder = new ConfigurationBuilder();
            builder.AddJsonFile("appsettings.json");

            var configuration = builder.Build();
            var options = configuration.Get<Options>();
            foreach (var kvp in options.Values)
                Console.WriteLine($"{kvp.Key}: {kvp.Value}");
        }
    }

    internal class Options
    {
        public Dictionary<string, bool> Values { get; } = new Dictionary<string, bool>();
    }
}

当给定此 appsettings.json 文件时,运行完美:

{
    "Values": {
        "a": true,
        "b": false
    }
}

但将 appsettings.json 内容更改为:

{
    "Values": {
        "a:b": true,
        "b": false
    }
}

我得到这个例外:

Unhandled Exception: System.InvalidOperationException: Cannot create instance of type 'System.Boolean' because it is missing a public parameterless constructor.

堆栈跟踪:

   at Microsoft.Extensions.Configuration.ConfigurationBinder.CreateInstance(Type type)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindDictionary(Object dictionary, Type dictionaryType, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindProperty(PropertyInfo property, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindNonScalar(IConfiguration configuration, Object instance, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.BindInstance(Type type, Object instance, IConfiguration config, BinderOptions options)
   at Microsoft.Extensions.Configuration.ConfigurationBinder.Get[T](IConfiguration configuration, Action`1 configureOptions)
   at ConsoleApp3.Program.Main() in D:\Dev\ConsoleApp3\ConsoleApp3\Program.cs:line 15

我做错了什么?请注意,在密钥中使用冒号是完全合法的 json,但可能不支持在 appsettings.json 文件中存储任何奇数字典?

引用Configuration in ASP.NET Core: Hierarchical configuration data

The Configuration API is capable of maintaining hierarchical configuration data by flattening the hierarchical data with the use of a delimiter in the configuration keys.

When the file is read into configuration, unique keys are created to maintain the original hierarchical data structure of the configuration source. The sections and keys are flattened with the use of a colon (:) to maintain the original structure

也就是说在下面的appsettings.json文件

{
    "Values": {
        "a:b": true,
        "b": false
    }
}

键将被扁平化为

  • 值:a:b
  • 值:b

ConfigurationBinder.BindDictionary 试图在 Options

中绑定 Dictionary<string, bool> 属性 时会破坏设置文件的结构

也参考这个GitHub Issue

Colons are reserved for special meaning in the keys, so they shouldn't be used as part of normal key values.