在開發(fā)企業(yè)級應(yīng)用的時候,通常會有不同的開發(fā)環(huán)境,比如有開發(fā)環(huán)境,測試環(huán)境,正式環(huán)境,生產(chǎn)環(huán)境等。在一份代碼部署到不同環(huán)境的時候,不同環(huán)境的配置文件可能需要根據(jù)目標環(huán)境不同而不同。比如在開發(fā)環(huán)境中,數(shù)據(jù)庫使用的是開發(fā)環(huán)境的數(shù)據(jù)庫,消息隊列也使用的部署在開發(fā)機上的消息隊列,傳統(tǒng)的方式是,由發(fā)布或者配置管理員來維護這些不同環(huán)境的配置文件。通常,手工的針對不同的環(huán)境去修改配置文件容易產(chǎn)生錯誤。
有很多種不同的方式來針對不同的部署環(huán)境生成配置,最笨的方法就是可以維護幾套不同的配置文件,然后在編譯事件中根據(jù)編譯環(huán)境變量來復(fù)制對應(yīng)的配置文件;還可以使用MSBuild中的PostBuild事件腳本去修改原始的配置文件,替換其中與目標環(huán)境相關(guān)的變量或者參數(shù);還有一些工具,比如ConfigGen,能夠根據(jù)額外的環(huán)境相關(guān)配置文件,來替換原始的配置文件。這里展示如何使用T4模板來生成不同的配置文件的。
T4模板是一種很流行的代碼生成引擎。.NET 里面的EntityFramework似乎也是使用該引擎來生成ORM代碼的。在Visual Studio能夠識別和支持T4模板文件。Visual Studio有一些Addin,比如T4 Editor 能夠很方便的輔助編寫T4模板文件。為了演示如何根據(jù)使用T4模板生成配置文件,首先創(chuàng)建一個簡單的控制臺應(yīng)用程序:
1. 打開Visual Studio創(chuàng)建一個控制臺應(yīng)用程序
2. 在默認的app.config配置文件中,添加一個數(shù)據(jù)庫連接字符串,比如:
<?xml version="1.0" encoding="utf-8" ?><configuration> <connectionStrings> <add name="Northwind" connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True" PRoviderName="System.Data.SqlClient" /> </connectionStrings></configuration>
3. 然后添加一個新的名為App.tt的文本文件,將App.config 中的內(nèi)容復(fù)制過來,然后做一些修改,如下:
<#@ template="" language="C#" #><#@ output="" extension= ".config" #><?xml version="1.0" encoding="utf-8" ?><configuration> <connectionStrings> <add name="Northwind" connectionString="Data Source=.;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings></configuration>
保存,就可以看到App.config已經(jīng)在App.tt下面了,Visual Studio能夠識別.tt文件,并且使用App.tt文件來生成App.config文件。App.config文件本身沒有發(fā)生變化,只是現(xiàn)在存在與App.tt中了。注意到,這里的數(shù)據(jù)庫是本地的數(shù)據(jù)庫。
4. 修改App.tt,使得數(shù)據(jù)庫連接字符串以參數(shù)的形式存在,如下:
<#@ template language="C#" #><#@ output extension= ".config" #><?xml version="1.0" encoding="utf-8" ?><configuration> <connectionStrings> <add name="Northwind" connectionString="<#= this.NorthwindConnectionString #>" providerName="System.Data.SqlClient" /> </connectionStrings></configuration><#+ string NorthwindConnectionString = "Data Source=.;Initial Catalog=Northwind;Integrated Security=True"; #>
在這個版本的App.tt中,NorthwindConnectionString現(xiàn)在是一個模板中的私有字段了。我們給他進行初始化,并且作為模板中參數(shù)的值。
5. 現(xiàn)在,添加一個新的名為Dev.tt的模板文件,內(nèi)容如下:
<# this.NorthwindConnectionString = "Data Source=DEV-SERVER;Initial Catalog=Northwind;Integrated Security=True"; #><#@ include file="App.tt" #>
這個模板文件包含了App.tt模板文件。這個里面的字符串配置會覆蓋App.tt中的字符串配置,這里可以看到,數(shù)據(jù)庫連接到了名為DEV-SERVER的服務(wù)器上。當保存Dev.tt的時候,Visual Studio會自動產(chǎn)生Dev.Config文件,然后將其添加到Dev.tt文件中。Deve.config文件內(nèi)容如下:
<?xml version="1.0" encoding="utf-8" ?><configuration> <connectionStrings> <add name="Northwind" connectionString="Data Source=DEV-SERVER;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings></configuration>
可以看到,這個配置文件和App.config的內(nèi)容很相似,只是數(shù)據(jù)庫服務(wù)器變成了DEV-SERVER.
6. 在Visual Studio中,設(shè)置Dev.config文件的Copy to Output Directory屬性為Copy if newer,這樣Visual Studio就會將該文件拷貝到編譯后的目錄中。
7. 修改部署腳本,將Dev.config拷貝到開發(fā)環(huán)境,而不是默認的 app.config。部署腳本也需要根據(jù)應(yīng)用程序的不同,將Dev.config重新名為目標應(yīng)用程序能夠識別的配置文件。比如本例中的Consoleapplication1.exe.config
8. 重復(fù)5-7步創(chuàng)建針對不同部署環(huán)境的config文件。
有時候,把所有的配置項都放在一個文件里面會使得整個文件看起來比較亂,所以可以對配置文件進行一些改進。 比如可以把針對數(shù)據(jù)庫連接字符串的配置connectionStrings移到一個單獨的文件里面,把AppSetting子項移到一個單獨的文件里。
一般的配置文件,Web.config 如下,這里面appSettings里面存了RabbitMQ消息隊列的配置,ConnectStrings里面存放了數(shù)據(jù)庫連接字符串:
<?xml version="1.0" encoding="utf-8" ?><configuration> <appSettings> <add key="RabbitMQHost" value="192.168.1.1"/> <add key="RabbitMQUserName" value="admin"/> <add key="RabbitMQUserPwd" value="11111" /> </appSettings> <connectionStrings> <add name="Northwind" connectionString="Data Source=DEV-SERVER;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /> </connectionStrings></configuration>
一種更好的做法是,將 appSettings 和 connectionStrings 放到各自的配置文件中,Web.config如下:
<?xml version="1.0" encoding="utf-8" ?><configuration > <appSettings file="Config/AppSetting.config"> </appSettings> <connectionStrings configSource="Config/ConnectionString.config"> </connectionStrings> </configuration>
在項目下創(chuàng)建了一個名為Config的文件夾,專門用來存放子項配置。AppSetting.config內(nèi)容如下:
<?xml version="1.0" encoding="utf-8" ?><appSettings> <add key="RabbitMQHost" value="192.168.1.1"/> <add key="RabbitMQUserName" value="admin"/> <add key="RabbitMQUserPwd" value="11111" /></appSettings>
ConnectionString.config 內(nèi)容如下:
<?xml version="1.0" encoding="utf-8" ?><connectionStrings> <add name="Northwind" connectionString="Data Source=DEV-SERVER;Initial Catalog=Northwind;Integrated Security=True" providerName="System.Data.SqlClient" /></connectionStrings>經(jīng)過這樣修改之后,主Web.config配置文件看起來比較簡潔,這里面可以放一些與部署平臺無關(guān)的配置,比如注冊的一些HttpHandler之類的。而另外一些和部署平臺有關(guān)的配置子項,如前面例子中的AppSetting,ConnectionString則可以做成T4模板文件,根據(jù)不同的部署環(huán)境生成對應(yīng)的配置項。最后需要注意的是,在編譯的時候在編譯事件中,需要將子項及其所在的文件夾一并復(fù)制到發(fā)布后的目錄下。這樣系統(tǒng)才能根據(jù)相對主配置文件的路徑找到子項的配置文件。
本文介紹了一種使用T4模板文件,在不同環(huán)境下自動生成相應(yīng)配置文件的方法,并介紹了對配置文件的改進,即把子配置項移到獨立的配置文件中,然后在將子項配置文件修改為模板文件的方法,這些方法在編譯和部署的時候,都需要編寫相應(yīng)的腳本,利用編譯工具的環(huán)境變量,將對應(yīng)環(huán)境的配置文件復(fù)制到編譯后的目錄下。這種方式教傳統(tǒng)的同一份代碼發(fā)布到不同的環(huán)境后,手動去維護和修改各個環(huán)境下的配置能夠減少錯誤的發(fā)生和工作量。希望本文介紹的內(nèi)容對大家在不同環(huán)境下生成配置文件有所借鑒和幫助。
新聞熱點
疑難解答