如何将配置源放置到某个配置节以避免密钥冲突?

时间:2017-09-28 09:59:33

标签: c# configuration .net-core .net-standard

我有两个配置文件:

users.json

{
  "Alice" : { "Email": "alice@example.com" },
  "Bob" : { "Email": "bob@example.com" }
}

connections.json

{
  "Database" : { "ConnectionString": "..." },
  "Gateway" : { "Url": "http://..." }
}

我正在尝试组建一个配置根目录:

var cfg = new ConfigurationBuilder()
    .AddJsonFile("users.json")
    .AddJsonFile("connections.json")
    .Build();

显然,我需要将每个配置源放入其部分:UsersConnections - 以避免冲突。某种前缀包装器可以完成这项工作,但我不想实现自己的。

如果您无法修改配置文件结构(在实际项目中有原因),您将如何处理这种情况?

2 个答案:

答案 0 :(得分:2)

相对于JsonConfigurationFileParserJsonConfigurationProvider类,实现看起来只能编写自己的FileConfigurationProvider实现。

作为一种解决方法,您可以执行以下操作(一步一步):

  • =>读取每个文件的配置
  • =>然后将结果作为KeyValuePair项目的集合
  • =>然后为每个键名添加一些自定义前缀(在您的情况下基于文件名)
  • =>合并:将最终集合作为MemoryCollection源附加到根配置

以下代码是构思实现,在使用prod之前可能需要修改:

public static class ConfigurationBuilderExtensions
{
    public static IConfigurationBuilder AddJsonFileWithPrefix(this IConfigurationBuilder configurationBuilder, string fileName, string prefix) 
    {
        var config = new ConfigurationBuilder()
            // you may need to set up base path again here
            // .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile(fileName).Build();

        var result = new List<KeyValuePair<string, string>>();

        foreach(var pair in config.AsEnumerable())
        {
            result.Add(new KeyValuePair<string, string>($"{prefix}:{pair.Key}", pair.Value));
        }

        return configurationBuilder.AddInMemoryCollection(result);
    }
} 

然后您可以将配置root创建为:

var cfg = new ConfigurationBuilder()
    .AddJsonFileWithPrefix("users.json", "users")
    .AddJsonFileWithPrefix("connections.json", "connections")
    .Build();

答案 1 :(得分:0)

您可以修改您的json文件以反映部分:

users.json:

{
    "Users": {
        "Alice" : { "Email": "alice@example.com" },
        "Bob" : { "Email": "bob@example.com" }
    }
}

和connections.json

{
    "Connections": {
        "Database" : { "ConnectionString": "..." },
        "Gateway" : { "Url": "http://..." }
    }
}