.NET Core 控制台应用程序,如何为每个环境配置 appSettings?

.NET Core console application, how to configure appSettings per environment?

我有一个 .NET Core 1.0.0 控制台应用程序和两个环境。我需要能够根据我在 运行 时设置的环境变量使用 appSettings.dev.jsonappSettings.test.json。通过依赖注入和 IHostingEnvironment 以及 EnvironmentName env,这对于 ASP.NET 核心 Web 应用程序来说似乎非常简单。变量,但是我应该如何为控制台应用程序连接(除了编写我自己的使用 Microsoft.Framework.Configuration.EnvironmentVariables 的自定义代码)?

谢谢。

我们在 .netcore 控制台应用程序中就是这样做的。这里的关键是在你的项目中包含正确的 dependencies可能不是全部,根据你的需要检查)和复制到输出 appSetting.json 作为你的 buildoptions

的一部分
  {
    "buildOptions": {
    "emitEntryPoint": true,
    "copyToOutput": {
       "include": [
       "appsettings*.json",
       "App*.config"
                 ]
          }
},
using Microsoft.Extensions.Configuration;
namespace MyApp
{
    public static void Main(string[] args)
    {
        var environmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
       

        var builder = new ConfigurationBuilder()
            .AddJsonFile($"appsettings.json", true, true)
            .AddJsonFile($"appsettings.{environmentName}.json", true, true)
            .AddEnvironmentVariables();
        var configuration = builder.Build();
        var myConnString= configuration.GetConnectionString("SQLConn");
    }
}

您可以为 ASP.Net 核心环境变量 (ASPNETCORE_ENVIRONMENT) 执行此操作:-

using Microsoft.AspNetCore.Hosting;
using System;

public class Program {
    private static string HostingEnvironment => Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
    private static bool IsEnvironment(string environmentName) => HostingEnvironment?.ToLower() == environmentName?.ToLower() && null != environmentName;

    private static bool Development => IsEnvironment(EnvironmentName.Development);
    private static bool Production => IsEnvironment(EnvironmentName.Production);
    private static bool Staging => IsEnvironment(EnvironmentName.Staging);

    public static void Main(string[] args) { // Your code here }
}

然后你可以简单地使用 属性

    public static void Main(string[] args) {
        if (Development){
            // Blow up the planet
        }
    }

您应该使用两个 IHostingEnvironment 接口。一个用于 ASP.NET 核心应用程序,另一个用于 .NET Core 控制台应用程序。您可以将此代码示例用于两者:

using System;
using System.IO;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.FileProviders;
using Microsoft.Extensions.Hosting.Internal;

namespace MyApplication.Common
{
    public static class ConfigurationFactory
    {
        /// <summary>
        /// Use for ASP.NET Core Web applications.
        /// </summary>
        /// <param name="config"></param>
        /// <param name="env"></param>
        /// <returns></returns>
        public static IConfigurationBuilder Configure(IConfigurationBuilder config, IHostingEnvironment env)
        {
            return Configure(config, env.EnvironmentName);
        }

        /// <summary>
        /// Use for .NET Core Console applications.
        /// </summary>
        /// <param name="config"></param>
        /// <param name="env"></param>
        /// <returns></returns>
        private static IConfigurationBuilder Configure(IConfigurationBuilder config, Microsoft.Extensions.Hosting.IHostingEnvironment env)
        {
            return Configure(config, env.EnvironmentName);
        }

        private static IConfigurationBuilder Configure(IConfigurationBuilder config, string environmentName)
        {
            return config
                .SetBasePath(Directory.GetCurrentDirectory())
                .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
                .AddJsonFile($"appsettings.{environmentName}.json", optional: true, reloadOnChange: true)
                .AddEnvironmentVariables();
        }

        /// <summary>
        /// Use for .NET Core Console applications.
        /// </summary>
        /// <returns></returns>
        public static IConfiguration CreateConfiguration()
        {
            var env = new HostingEnvironment
            {
                EnvironmentName = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") ?? "Production",
                ApplicationName = AppDomain.CurrentDomain.FriendlyName,
                ContentRootPath = AppDomain.CurrentDomain.BaseDirectory,
                ContentRootFileProvider = new PhysicalFileProvider(AppDomain.CurrentDomain.BaseDirectory)
            };

            var config = new ConfigurationBuilder();
            var configured = Configure(config, env);
            return configured.Build();
        }
    }
}

对于使用 .NET Core 2.1.0+ 和 Microsoft.Extensions.Hosting 来托管您的控制台应用程序的用户,您可以使用以下代码(根据 Feiyu Zhou 在另一个线程中的 ):

var hostBuilder = new HostBuilder()
    .ConfigureHostConfiguration(config =>
    {
        if (args != null)
        {
            // enviroment from command line
            // e.g.: dotnet run --environment "Staging"
            config.AddCommandLine(args);
        }
    })
    .ConfigureAppConfiguration((context, builder) =>
    {
        builder.SetBasePath(AppContext.BaseDirectory)
            .AddJsonFile("appsettings.json", optional: false)
            .AddJsonFile($"appsettings.{context.HostingEnvironment.EnvironmentName}.json", optional: true);
    })

它是这样的,对于 dotnet 2.x 核心控制台应用程序:

        using Microsoft.Extensions.Configuration;
        using Microsoft.Extensions.DependencyInjection;
        using Microsoft.Extensions.Logging;

        [...]
        var configuration = new ConfigurationBuilder()
            .SetBasePath(Directory.GetCurrentDirectory())
            .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
            .AddEnvironmentVariables()
            .Build();
        var serviceProvider = new ServiceCollection()
            .AddLogging(options => options.AddConfiguration(configuration).AddConsole())
            .AddSingleton<IConfiguration>(configuration)
            .AddSingleton<SomeService>()
            .BuildServiceProvider();
        [...]
        await serviceProvider.GetService<SomeService>().Start();

您可以在 SomeService.

中注入 ILoggerFactory、IConfiguration

如果像我一样,您只是想为发布和开发模式使用不同的配置文件,只需添加一个 appsettings.Development.json 文件,并将文件的 属性 中的 CopyToOutputDirectory 设置设置为 true window.

现在,要根据构建配置访问文件,您可以使用 #if DEBUG preprocessor directive

这是一个例子:

static void Main(string[] args)
{

#if DEBUG
    var builder = new ConfigurationBuilder()
            .AddJsonFile($"appsettings.Development.json", true, true);
#else
    var builder = new ConfigurationBuilder()
            .AddJsonFile($"appsettings.json", true, true);
#endif

    var configuration = builder.Build();

    // ... use configuration
}

这些环境方面的事情似乎对大多数人都有效,但我完全不同意所有环境管理。 运行时间和目标系统都不知道它是什么。只有您,作为开发人员或部署机制,才知道目标系统是什么。

每个人都在谈论 ASPNETCORE_ENVIRONMENT 变量,甚至像这里 https://docs.microsoft.com/en-us/aspnet/core/fundamentals/environments?view=aspnetcore-3.0 这样的官方文档也是如此。但实际上必须有人明确定义一个系统作为生产系统,例如,通过手动设置 ASPNETCORE_ENVIRONMENT 一次。你真的想假设并依赖它已经在你使用的每个环境中设置了吗?不,你不能。如果您必须将控制台应用程序部署到没有网站 运行ning 的批处理服务器怎么办? ASPNETCORE_ENVIRONMENT 不可用。如果您需要在没有 IIS 的情况下仅使用 kestrel 部署和 运行 一个 .net 核心 webapi 怎么办?没有 web.config 也没有环境变量。您希望您的 admins/operation 团队为您的控制台应用程序设置这个误导性变量吗?在这种情况下,我看到很多项目每个项目都有这样的应用程序设置:

appsettings.json
appsettings.development.json
appsettings.test.json
appsettings.uat.json
appsettings.staging.json
appsettings.production.json

请记住,默认情况下,这些文件中的每一个都将发布并部署到目标系统。乍一看,让环境 "decide" 应该使用哪个配置看起来很容易。但是您在不适合它的系统上部署了配置和可能的凭据。

结论

我推荐appsettings.json + appsettings.release.json。第一个仅适用于开发人员。改变它,随心所欲地玩它。最后一个是准备部署的 VALID 配置(过程)。在部署开始之前,转换配置以便为目标系统做好准备。而已。无需依赖目标机器上的设置,没有混乱的配置。即使服务器快速变化(如一般扩展、虚拟机、云等),也能完全控制您的应用程序

我感谢建设性的反馈:-)

对于 .NetCore 3.1 和使用 .CreateDefaultBuilder(args) 扩展的任何人。只需将 -environment "Development" 添加到调试设置中的命令行参数即可。完成。

从 Net Core 3.1++ 开始,通用主机 class Microsoft.Extensions.Hosting.Host 使用 DOTNET_ENVIRONMENT 环境变量而不是 ASPNETCORE_ENVIRONMENT。

在项目调试设置中设置 DOTNET_ENVIRONMENT="Development" 无需任何额外编码即可工作。

或者您可以像这样添加自己的前缀:

// works for WPF but should work similar for Console Apps
public partial class App : Application
{
    private readonly IHost _host;

    public App()
    {
        _host = Host.CreateDefaultBuilder()
            .ConfigureHostConfiguration(configHost => {
                configHost.AddEnvironmentVariables(prefix: "PREFIX_");
            })
            .ConfigureServices((context, services) =>
            {
                ConfigureServices(context.Configuration, services);
            })
            .Build();
    }

    private void ConfigureServices(
        IConfiguration configuration,
        IServiceCollection services)
    {
       // ...
    }

    // ...
}