在 hostBuilder.ConfigureAppConfiguration 中获取 env 的规定方法

Prescribed way to obtain env in hostBuilder.ConfigureAppConfiguration

喜欢触发重复的关闭者请仔细阅读问题并避免将其错误地标记为重复。

本题不是一般的获取环境名称的题。我知道很多方法。问题是如何获得保证与最终将从 HostingEnvironment.EnvironmentName

提供的值一致的值

这个问题是关于控制台应用程序的。它与网络应用程序无关,即使您刚刚弄清楚如何使用网络应用程序执行此操作并且想告诉所有人。不涉及 Startup.cs。依赖于默认 Web 主机的答案无法解决问题。

主机生成器设置如下所示。

      var hostBuilder = Host.CreateDefaultBuilder(args);
      hostBuilder
      .ConfigureHostConfiguration(configurationBuilder =>
      {
        configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
        configurationBuilder.AddEnvironmentVariables(prefix: "AED_COORDINATOR_");
        configurationBuilder.AddCommandLine(args);
      })
      .ConfigureAppConfiguration(configurationBuilder => 
      {
        var env = Environment.GetEnvironmentVariable($"{ENV_PREFIX}ENVIRONMENT");
        configurationBuilder
        .AddJsonFile("appSettings.json", false, true)
        .AddJsonFile($"appSettings.{env}.json", true, true);
      })
      ...

有了这个 launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": ".NET Core Launch (console)",
      "type": "coreclr",
      "request": "launch",
      "preLaunchTask": "build",
      "program": "${workspaceFolder}/bin/Debug/netcoreapp3.1/aed.coordinator.dll",
      "args": [
        "--environment=Production"
      ],
      "cwd": "${workspaceFolder}",
      "console": "integratedTerminal",
      "stopAtEntry": false,
      "env": {
        "AED_COORDINATOR_ENVIRONMENT": "Development"
      }
    },

运行 它产生这个。

问题是 appSettings.Development.json 被加载,因为 Environment.GetEnvironmentVariable($"{ENV_PREFIX}ENVIRONMENT") 没有考虑命令行参数。

我知道可以扩展此代码以显式考虑命令行参数,但命令行参数的可靠解析并非易事,无论如何,如果您必须内联所有内容,那么拥有构建器的意义何在?更糟糕的是,他们可能不同意。

那么,有没有什么办法可以使用builder(已经配置好这方面的)来解决环境问题了?

您不能多次调用 .Build(),因此无法部分配置构建器,构建中间主机,从中提取已解析的环境,然后完成配置。

可以这样做。

      var ENV_PREFIX = "AED_COORDINATOR_";
      string env;
      using (var envHost = Host.CreateDefaultBuilder(args).ConfigureHostConfiguration(configurationBuilder =>
      {
        configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
        configurationBuilder.AddEnvironmentVariables(prefix: ENV_PREFIX);
        configurationBuilder.AddCommandLine(args);
      }).Build())
        env = envHost.Services.GetService<IHostEnvironment>().EnvironmentName;

这里提前解决了env,妥善处理了builder和中间宿主,其余代码基本没变。

但是,没有必要这样做。

在提供给 hostBuilder.ConfigureServices() 的 lambda 中,我正在检查服务,发现无论如何神奇地添加了 appSettings.{env}.json — 虽然上面的代码是成功的,但 appSettings.jsonappSettings.{env}.json 出现 两次 作为提供者 — 并且主机构建器使用了正确的环境,所以整个

      .ConfigureAppConfiguration(configurationBuilder =>
      {
        configurationBuilder
        .AddJsonFile("appSettings.json", false, true)
        .AddJsonFile($"appSettings.{env}.json", true, true);
      })

不需要。

这意味着如果你这个部分正确

.CreateDefaultBuilder(args).ConfigureHostConfiguration(configurationBuilder =>
{
  configurationBuilder.AddJsonFile("hostsettings.json", optional: true);
  configurationBuilder.AddEnvironmentVariables(prefix: ENV_PREFIX);
  configurationBuilder.AddCommandLine(args);
})

你不需要休息。

后面的代码甚至可以使用配置:

      .ConfigureServices((hostContext, services) =>
      {
        services.AddConfig(hostContext.Configuration);
        services.AddHostedService<Worker>();
      });

AddConfig 方法是一种扩展方法,它准备选项 类 以供依赖项注入使用。

    public static IServiceCollection AddConfig(this IServiceCollection services, IConfiguration config)
    {
      var section = config.GetSection(MosquittoOptions.SectionName);
      services.Configure<MosquittoOptions>(section);
      section = config.GetSection(ServicesLayerOptions.SectionName);
      services.Configure<ServicesLayerOptions>(section);
      return services;
    }