【问题标题】:Expand environment variables in appSettings.json file在 appSettings.json 文件中展开环境变量
【发布时间】:2020-03-14 12:31:52
【问题描述】:

有没有办法“开箱即用”让appsettings.json 值中的环境变量自动扩展?

举一个人为的例子:

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

我的目标是能够通过更改单个环境变量来切换我的环境,并让它影响多个 appsetting 值,而不是拥有每个环境的配置文件。

更新

我查看了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 配置还很陌生,这就引出了第二个问题:

如何让这个自定义实现替换标准实现? IE。删除默认的 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?
        }
        );

【问题讨论】:

  • 我认为你已经找到了唯一的解决方案,否则通过 github/nuget 进行搜索。
  • ConfigureAppConfiguration 有几个选项。默认设置是this(请参阅最后一个项目符号,“应用程序配置来自:”)。你仍然想要所有这些资源,以相同的顺序,还是你可以简化?例如你可以只有一个来源,即带有 env 替换的 appsettings.json 文件吗?
  • @KirkLarkin - 我想替换前两个源,appsettings.json 和 appsettings.{Environment}.json。因此它的行为类似于其他开发人员熟悉的默认配置,只是它添加了环境变量扩展。
  • 我会说你有两个选择:1 读取配置并用你的环境替换“占位符”......但这只是 hacky......我只会使用普通的多文件.net 核心中可用的系统已经像 appsettings.json 和 appsetings.environmentname.json

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


【解决方案1】:

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

  1. IConfigurationSource
  2. IConfigurationProvider

这是添加到IConfigurationBuilder 源的IConfigurationSource 实现。这个实现还负责创建自己的IConfigurationProvider,它负责从源加载数据。

这是IConfigurationSource (ExpandJsonConfigurationSource) 和IConfigurationProvider (ExpandJsonConfigurationProvider) 的自定义实现:

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),
            StringComparer.OrdinalIgnoreCase);
    }
}

这里没有很多事情发生。这些实现只是遵循与现有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. 对于每个实例:

  3. 确定实例在预配置源中的位置。

  4. 删除实例。

  5. 将删除的实例替换为ExpandJsonConfigurationSource 的实例,跨属性复制以确保它具有相同的路径、可选标志等。

【讨论】:

  • 很高兴从编写有关该主题的 Microsoft 文档的人那里得到答案!我想如果我知道没有其他来源,我可以简单地执行“configuration.Sources.Clear();”就像他们在docs.microsoft.com/en-us/dotnet/core/extensions/… 中所做的那样,然后添加。
  • @GöranRoseen 是的,没错。通过这样做,您可以获得完全控制权,但当然会失去默认值。
【解决方案2】:

我创建了一个库来执行变量替换,它从 any 配置源替换,而不仅仅是环境变量。 见: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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2010-12-26
    • 2012-12-21
    • 1970-01-01
    • 2023-03-07
    相关资源
    最近更新 更多