首页 > 其他分享 >用编译配置与环境变量实现开发时切换配置文件

用编译配置与环境变量实现开发时切换配置文件

时间:2022-10-11 13:57:43浏览次数:106  
标签:配置文件 代码 配置 options 编译 services 环境变量

开发人员在开发代码的时候,经常会使用到DebugReleaseDevelopmentProduction等几个概念,虽然有些地方在功能上最终殊途同归,但是还是有非常大的区别。

首先需要搞清楚,Debug、Release都属于编译配置,而Development、Production则属于环境配置。

作为开发者,开发时如果需要切换开发与发布环境的配置文件,两种方案都可以实现。

编译配置

思路很简单,在Debug模式下,就使用开发版本的配置项,在Release模式下,就使用正式版的配置项。开发的时候,只要通过鼠标点点切换就好了,非常方便。

Debug与Release控制编译器的行为,两者的区别挺多的,其中编译器优化这个可以查看我的一篇上古的文章。Debug配置定义了编译符号:DEBUG,Release定义了编译符号:RELEASE。
在代码中可以通过两种方式感知这个编译符号:

使用编译器预处理指令#if

public static async Task Main(string[] args)
{
    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
           var provider = services.BuildServiceProvider();
#if DEBUG
           services.AddDbContext<ManagementDataContext>(options =>
        options.UseNpgsql(provider.GetRequiredService<IConfiguration>().GetConnectionString("DebugConnection")));
#else
           services.AddDbContext<ManagementDataContext>(options =>
        options.UseNpgsql(provider.GetRequiredService<IConfiguration>().GetConnectionString("ReleaseConnection")));
#endif
        })
        .Build();

    await host.RunAsync();
}

编译器预处理语句,优点是简单,缺点是需要选择的分支特别多时,显得非常乱。

预处理语句将在编译中直接生成对应的代码,编译完成的程序中,看不到任何有关选择的过程。

使用ConditionalAttribute

ConditionalAttribute是一种特性标识,可以读取调用方(如果没有就是自己)的编译符号自动选择代码。

[Conditional("DEBUG")]
private static void ConfigNpgsqlDebug(IServiceCollection services)
{
    var provider = services.BuildServiceProvider();
    services.AddDbContext<ManagementDataContext>(options =>
        options.UseNpgsql(provider.GetRequiredService<IConfiguration>().GetConnectionString("DebugConnection")));
}
[Conditional("RELEASE")]
private static void ConfigNpgsqlRelease(IServiceCollection services)
{
    var provider = services.BuildServiceProvider();
    services.AddDbContext<ManagementDataContext>(options =>
        options.UseNpgsql(provider.GetRequiredService<IConfiguration>().GetConnectionString("ReleaseConnection")));
}

public static async Task Main(string[] args)
{
    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
ConfigNpgsqlDebug(services);
ConfigNpgsqlRelease(services);
        })
        .Build();

    await host.RunAsync();
}

注意,编译器会根据实际情况将对应代码编译进程序中,Debug模式下,Release段的代码和对应的引用都不会执行。这种方式比较优雅简洁,不过只能标识方法或者属性,有一定局限性。

ConditionalAttribute会保留到最终的程序集中,因此在编译后的程序中能看到这个Attribute。

环境配置

思路是程序在运行的过程中,读取环境变量,通过不同的环境变量切换不同的配置文件。

关于环境配置官方有一篇非常详细的文档。我们就使用默认的Development和Production两种环境变量配置。环境变量并不能在代码中固化,在开发时,需要使用设置对应的IDE环境。将配置分别写在appsettings.Development.jsonappsettings.Production.json两个文件中,配置项目都为MonitorConnection,只是值不同。

官方文档对配置文件会加载appsettings.{Environment}.json,默认情况下,如果不指定环境变量,那么会认为是Production

调用代码非常简单,不需要对环境进行的特别识别:

public static async Task Main(string[] args)
{
    IHost host = Host.CreateDefaultBuilder(args)
        .ConfigureServices(services =>
        {
            services.AddDbContext<ManagementDataContext>(options =>
                options.UseNpgsql(Configuration.GetConnectionString("MonitorConnection")));
        })
        .Build();

    await host.RunAsync();
}

然后我们设置IDE,以VS为例,找到项目对应的launchSettings.json,修改成类似如下的代码。

"profiles": {
    "WebApi(Dev)": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    "WebApi(Prod)": {
      "commandName": "Project",
      "launchBrowser": true,
      "launchUrl": "swagger",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Production"
      }
    }
  }

保存文件,在IDE上面就能出现这样的界面。

这样就能通过选择不同的运行环境来自动切换不同的配置文件了。

总结

两种方法虽然最终的结果类似,但是区别还是挺大的:

  • 使用编译配置,运行时将保持固定,不能再切换;而环境配置可以通过变更环境变量的形式动态调整(对docker友好)。
  • 使用编译配置,往往同时绑定编译时候的其他flag(优化、pdb生成之类),不是非常灵活。
  • 代码上,使用编译配置往往需要使用更多的代码实现,而环境变量往往不需要额外的代码。

综上,个人认为使用环境变量进行切换会更加方便与灵活。

参考

标签:配置文件,代码,配置,options,编译,services,环境变量
From: https://www.cnblogs.com/podolski/p/16777738.html

相关文章

  • 在 macOS 中用 gcc 替换 clang 作为 VSCode 编译器
    众所周知,macOS下的默认C/C++编译器是clang/clang++而非gcc/g++,尽管在大部分情况下或许难以察觉其中的区别,但偶尔我们会需要用到gcc中的一些函数等等,因此改用VSCod......
  • Go 的交叉编译
    使用Golang的交叉编译|Linux中国https://mp.weixin.qq.com/s?src=11&timestamp=1665454252&ver=4097&signature=IkXAz0lpJPRmZKSzVXdOa4cwyiHPhfQvC5CAwJb0q5vnqvTiD......
  • 1. 查看NGINX是否在运行. 四种方式 nginx的配置文件的路径: /etc/nginx/nginx.conf
    查看NGINX是否在运行.1.查看NGINX是否在运行.psaux|grepnginx[root@bogon/]#psaux|grepnginxroot23180.00.0568161272?Ss......
  • Linux 程序用什么 gcc 版本编译
    查看用什么gcc版本编译的readelf-p.comment/usr/local/python39/bin/python3 结果:Stringdumpofsection'.comment':[0]GCC:(GNU)4.8.52015062......
  • Java环境变量配置
    pathpath是一个常见的环境变量,它告诉系统除了在当前目录下寻找程序外,还可以到path指定的目录中寻找。在末尾加上:;%JAVA_HOME%\bin;%JAVA_HOME%\jre\binclasspathJDK1.5......
  • vite配置文件语法提示以及开发环境和生产环境区分
    1.让vite.config.js具备语法提示:方法1:使用defineConfig方法:vite.config.js需要导出一个配置对象:exportdefault{...}但是这样是不会具备配置提示能力的,d......
  • SpringBoot配置文件的优先级
    配置文件优先级(1)命令行参数;(2)java:comp/env的JNDI属性(当前J2EE应用的环境);(3)JAVA系统的环境属性;(4)操作系统的环境变量;(5)JAR包外部的application-xxx.properties或applica......
  • 解读Vue3模板编译优化
    今天的文章打算学习下Vue3下的模板编译与Vue2下的差异,以及VDOM下Diff算法的优化。编译入口了解过Vue3的同学肯定知道Vue3引入了新的组合Api,在组件mount阶......
  • 动态编译库 Natasha 5.0 兼容版本发布
    Natasha5.0版本已于2022/10/10日发布,此次大版本更迭带来了兼容性支持,目前Natasha可以兼容standard2.0及coreapp3.1以上版本.下载使用NuGet\Install-Packa......
  • 一、读取配置文件low代码-16
    1、安装第三方扩展包MicrosoftWindows[版本10.0.19044.2006](c)MicrosoftCorporation。保留所有权利。C:\Users\jieqiong>pipinstallConfigparserCollecting......