问题
The following program:
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>();
}
}
When given this appsettings.json
file, runs perfectly:
{
"Values": {
"a": true,
"b": false
}
}
but change the appsettings.json
contents to this:
{
"Values": {
"a:b": true,
"b": false
}
}
and I get this exception:
Unhandled Exception: System.InvalidOperationException: Cannot create instance of type 'System.Boolean' because it is missing a public parameterless constructor.
stack trace:
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
What am I doing wrong? Note that having a colon in the key is perfectly legal json, but perhaps storing any odd dictionary in the appsettings.json file is not supported?
回答1:
Reference 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
That means that in the following appsettings.json file
{
"Values": {
"a:b": true,
"b": false
}
}
The keys would be flattened to
- Values:a:b
- Values:b
which is going to break the structure of settings file when the ConfigurationBinder.BindDictionary tries to bind the Dictionary<string, bool>
property in the Options
Also referencing this GitHub Issue
Colons are reserved for special meaning in the keys, so they shouldn't be used as part of normal key values.
来源:https://stackoverflow.com/questions/52121374/net-core-configuration-manager-reading-a-dictionary-where-one-key-has-a-colon