开发人员在开发代码的时候,经常会使用到Debug、Release、Development、Production等几个概念,虽然有些地方在功能上最终殊途同归,但是还是有非常大的区别。
首先需要搞清楚,Debug、Release都属于编译配置,而Development、Production则属于环境配置。
作为开发者,开发时如果需要切换开发与发布环境的配置文件,两种方案都可以实现。
思路很简单,在Debug模式下,就使用开发版本的配置项,在Release模式下,就使用正式版的配置项。开发的时候,只要通过鼠标点点切换就好了,非常方便。

Debug与Release控制编译器的行为,两者的区别挺多的,其中编译器优化这个可以查看我的一篇上古的文章。Debug配置定义了编译符号:DEBUG,Release定义了编译符号:RELEASE。
在代码中可以通过两种方式感知这个编译符号:
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();
}
编译器预处理语句,优点是简单,缺点是需要选择的分支特别多时,显得非常乱。
预处理语句将在编译中直接生成对应的代码,编译完成的程序中,看不到任何有关选择的过程。
ConditionalAttributeConditionalAttribute是一种特性标识,可以读取调用方(如果没有就是自己)的编译符号自动选择代码。
[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.json和appsettings.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上面就能出现这样的界面。

这样就能通过选择不同的运行环境来自动切换不同的配置文件了。
两种方法虽然最终的结果类似,但是区别还是挺大的:
综上,个人认为使用环境变量进行切换会更加方便与灵活。
我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看rubyzip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d
我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时
我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,
Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题
对于具有离线功能的智能手机应用程序,我正在为Xml文件创建单向文本同步。我希望我的服务器将增量/差异(例如GNU差异补丁)发送到目标设备。这是计划:Time=0Server:hasversion_1ofXmlfile(~800kiB)Client:hasversion_1ofXmlfile(~800kiB)Time=1Server:hasversion_1andversion_2ofXmlfile(each~800kiB)computesdeltaoftheseversions(=patch)(~10kiB)sendspatchtoClient(~10kiBtransferred)Cl
我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚
使用带有Rails插件的vim,您可以创建一个迁移文件,然后一次性打开该文件吗?textmate也可以这样吗? 最佳答案 你可以使用rails.vim然后做类似的事情::Rgeneratemigratonadd_foo_to_bar插件将打开迁移生成的文件,这正是您想要的。我不能代表textmate。 关于ruby-使用VimRails,您可以创建一个新的迁移文件并一次性打开它吗?,我们在StackOverflow上找到一个类似的问题: https://sta
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我正在从erb文件切换到HAML。我将hamlgem添加到我的系统中。我创建了app/views/layouts/application.html.haml文件。我应该只删除application.html.erb文件吗?此外,仍然有/public/index.html文件被呈现为默认页面。我想创建自己的默认index.html.haml页面。我应该把它放在哪里以及如何使系统呈现该文件而不是默认索引文件?谢谢! 最佳答案 是的,您可以删除任何已转换为HAML的View的ERB版本。至于你的另一个问题,删除public/index/h
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击