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