在appSettings.json文件中展开环境变量

时间:2020-03-14 12:31:52

标签: c# asp.net-core .net-core asp.net-core-2.1

是否有一种“开箱即用”的方法来自动扩展appsettings.json值中的环境变量?

举一个人为的例子:

{
  ...
  "MyPath1": "C:/MyApp/%ENV%/Myfolder1/MyFile1.dat",
  "MyConnectionString":  "Server=MyServer%ENV%..."
  ...
}

我的目标是能够通过更改单个环境变量来切换我的环境,并使其影响多个应用程序设置值,而不是具有每个环境的配置文件。

更新

我已经浏览了the source code of JsonConfigurationProvider,据我所知,没有开箱即用的功能。

我看到应该可以通过从JsonConfigurationProvider派生自定义类并覆盖Load()方法来实现:

public override void Load()
{
    base.Load();
    foreach(var key in Data.Keys)
    {
        Data[key] = Environment.ExpandEnvironmentVariables(key);
    }
}

但是我对.NET Core配置还很陌生,这导致了第二个问题:

如何获得此自定义实现以取代标准实现?即删除默认的appsettings.json和appsettings.environment.json提供程序并替换为自定义提供程序。大概要在Program.cs中添加一些东西:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureAppConfiguration(config =>
        {
            config.??? what do I need here?
        }
        );

2 个答案:

答案 0 :(得分:3)

要创建和使用自定义配置源,需要两个实现:

  1. IConfigurationSource
  2. IConfigurationProvider

IConfigurationSource实现添加到IConfigurationBuilder的源中。此实现还负责创建自己的IConfigurationProvider,负责从源加载数据。

这是IConfigurationSourceExpandJsonConfigurationSource)和IConfigurationProviderExpandJsonConfigurationProvider)的自定义实现:

public class ExpandJsonConfigurationSource : JsonConfigurationSource
{
    public override IConfigurationProvider Build(IConfigurationBuilder builder)
    {
        EnsureDefaults(builder);
        return new ExpandJsonConfigurationProvider(this);
    }
}

public class ExpandJsonConfigurationProvider : JsonConfigurationProvider
{
    public ExpandJsonConfigurationProvider(ExpandJsonConfigurationSource source)
        : base(source) { }

    public override void Load()
    {
        base.Load();
        Data = Data.ToDictionary(
            x => x.Key,
            x => Environment.ExpandEnvironmentVariables(x.Value));
    }
}

这里没有很多事情。这些实现仅遵循与现有JsonConfigurationSourceJsonConfigurationProvider实现相同的方法,并具有用于扩展环境变量的自定义处理。

要替换基于JSON的预配置源,请使用以下命令:

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>()
        .ConfigureAppConfiguration((ctx, builder) =>
        {
            var jsonConfigurationSources = builder.Sources
                .OfType<JsonConfigurationSource>()
                .ToList();

            foreach (var jsonConfigurationSource in jsonConfigurationSources)
            {
                var indexOfJsonConfigurationSource = builder.Sources
                    .IndexOf(jsonConfigurationSource);

                builder.Sources.RemoveAt(indexOfJsonConfigurationSource);
                builder.Sources.Insert(
                    indexOfJsonConfigurationSource,
                    new ExpandJsonConfigurationSource
                    {
                        FileProvider = jsonConfigurationSource.FileProvider,
                        Path = jsonConfigurationSource.Path,
                        Optional = jsonConfigurationSource.Optional,
                        ReloadOnChange = jsonConfigurationSource.ReloadOnChange
                    });
            }
        });

传入ConfigureAppConfiguration的委托执行以下操作:

  1. 找到JsonConfigurationSource的所有已配置实例。应该有两个实例:appsettings.json和例如appsettings.Development.json
  2. 对于每个实例:

    1. 确定实例在预配置源中的位置。
    2. 删除实例。
    3. 使用实例ExpandJsonConfigurationSource替换已删除的实例,在属性之间进行复制以确保其具有相同的路径,可选标志等。

答案 1 :(得分:1)

我创建了一个库来执行变量替换,它从任何配置源进行替换,而不仅仅是环境变量。 参见:https://github.com/molinch/ConfigurationSubstitutor

您只需要将其注册为另一个配置源,即可通过在ConfigurationBuilder上调用.EnableSubstitutions()来完成。

以您的示例为例:

  • 如果在appsettings.json中,您拥有:"MyPath": "C:/MyApp/%ENV%/Myfolder1/MyFile1.dat"
  • 并且您具有以下环境变量:ENV = Foo
  • 然后您应启用替代功能,
.EnableSubstitutions("%", "%")

最后,从配置请求MyPath时,您将获得:C:/MyApp/Foo/Myfolder1/MyFile1.dat