我們要尋求一種避免直接寫代碼的應用程式配置和資訊設定方法,我們已經建立了多種不同的策略來儲存配置資訊。而我們是要尋求一種正確的方法,我們要不斷提高和改我們的想法,關於哪裡是放置這些資訊的好地方。INI檔案?這是Windows3.1做的事,配置資訊的結構是受限制的,而且在檔案名稱上可能還會與其它程式程式相衝突。註冊表?是的,是這個正確的想法,但它也有它的限制。亂七八糟的程式可能會通過在註冊表裡寫一些錯誤資訊來嚴重破壞電腦。正因為寫註冊表存在危險,一個應用程式必須有管理員權限來寫註冊表的一部份。你的所有使用者都會是以具有修改註冊表權利的管理員身份在運行嗎?希望不是,如果你使用註冊表,而你的使用者不是以管理員身份啟動並執行,在試圖讀寫註冊表時,將會得到一個異常和錯誤。
謝天謝地,還有很多更好的方法來儲存設定資訊,這樣你的程式可以根據使用者的選擇不同適應不同的行為,例如安裝參數,機器設定,或者其它任何事情。.Net架構提供了一個標準的設定位置,這樣你的程式可以使用它來儲存配置資訊。這些儲存位置是由應用程式特別指定的,而且當程式執行的機器上的使用者被限制了許可權時一樣可以有效工作。
唯讀資訊是屬於設定檔的,XML檔案控制應用程式中不同類型的行為;定義的結構表指明了所有的元素和屬性,而這些都是.NET FCL從設定檔中分析出來的。 這些元素控制一些設定,例如正在使用那個架構版本,支援的調試層級,以及程式集的搜尋路徑。有一個節點你是必須要明白的,那就是appSettings部份,它可以同時應用與web應用程式和傳統型應用程式。運行程式在啟動時讀取這一節點的資訊,它載入所有的關鍵字和值到一個屬於應用程式的名字值集合(NameValueCollection)中。這是你自己程式的一部份,你可以添加任何程式須要的值來控製程序行為。當修改設定檔時,也就修改了程式行為。
對於使用設定檔來說,ASP.Net應用程式比傳統型應用程式的伸縮性稍靈活一點。每個個虛擬目錄可以有一個自己的設定檔,這個檔案被每個虛擬目錄依次讀取,而每個虛擬目錄也就對應一個URL的一部分。The most local wins. 例如,這個URL:http://localhost/MyApplication/SubDir1/SubDir2/file.aspx 可能被4個不同的設定檔所控制。machine.config最先讀取,其次是在MyApplication中的web.config檔案,接著是在SubDir1 和SubDir2中的web.config檔案。而它們每一個都可以修改前一個設定檔設定的值,或者是添加自己鍵/值對。你可以通過這種設定繼承方式,來配置一個全域應用程式的參數選擇,而且可以限制一些私人資源的訪問。web應用程式在不同的虛擬目錄中有不同的配置。
在傳統型應用程式中,對於每個應用程式定義域只有一個應用程式程式設定檔。.Net運行時在載入每個可執行檔時,為它建立一個預設的應用程式定義域,然後讀取一個預先軍定義的設定檔到這個應用程式定義域中。預設的設定檔在與應用程式運行時的同一個目錄中,而且就以<應用程式名稱>.<副檔名>.config來命名的。例如:MyApp.exe可能就有一個名為MyApp.exe.config的設定檔。appsettings部份可以用於建立你自己的鍵/值對到應用程式中。
設定檔是儲存一些控製程序行為的資訊的最好的地方。但你可能很快會發現,應用程式沒有API來寫設定檔資訊。設定檔不是用於儲存任何有序設定的地方。不要急著寫註冊表,也不要自己亂寫。這裡有一個更好的方法讓你配置傳統型應用程式。
你可能須要定義設定檔的格式,而且把設定檔放到正確的地方。通過在全域設定上定義一些設定結構和添加公用的讀寫屬性,你可以很簡單的儲存和取回這些設定:
[ Serializable( ) ]
public struct GlobalSettings
{
// Add public properties to store.
}
XML序列化來儲存你的設定:
XmlSerializer ser = new XmlSerializer(
typeof( GlobalSettings ));
TextWriter wr = new StreamWriter( "data.xml" );
ser.Serialize( wr, myGlobalSettings );
wr.Close( );
使用XML格式就意味著你的設定可以很容易的閱讀,很容易的解析,以及很容易的去調試。如果須要,你可以對這些使用者佈建進行加密儲存。這隻是一個使用XML序列化的例子,不是對象持久序列化。XML序列化隱藏檔,不是整個對象樹。配置設定以及使用者佈建一般不會包含網狀對象,而且XML序列化是一個簡單的檔案格式。
最後一個問題就是,應該在哪裡儲存這些資訊。你應該在三個不同的地方放置配置資訊檔。選擇哪一個要根據配置的使用方式:全域,單使用者,或者單使用者且單機器。這三個位置可以通過調用System.Environment.GetFolderPath() 而取得。你應該在GetFolderPath()返回的路徑後添加上應用程式的詳細目錄。請格外小心的在所有使用者或者機器範圍上填寫資訊。這樣做要在目標機器是取得一些特權。
Environment.SpecialFolder.CommonApplicationData返回儲存資訊的目錄,這一目錄是被機器上的所有使用者所共用的。如果在一台機上使用的是預設安裝,GetFolderPath(SpecialFolder.CommonApplicationData)會返回 C:\Documents and Settings\All Users\Application Data。儲存在這一目錄的的設定應該是被機器上的所有使用者所使用的。當你要在這裡建立資訊時,讓安裝程式給你做或者以管理員模式進行。不應該在這裡寫一些使用者級(譯註:users級是windows裡的一個使用者組,權利比管理員小。)的程式資料。偶然可能會讓你的應用程式在使用者機上沒有足夠的許可權來訪問。
Environment.SpecialFolders.ApplicationData返回目前使用者的路徑,而且在網路上被所有機器共用的。在預設安裝中,GetFolderPath(SpecialFolders.ApplicationData)返回 C:\Documents and Settings\<使用者名稱>\Application Data。每個使用者有他(或她)自己的應用程式資料目錄。當使用者登入到一個域是,使用這個列舉進入到共用網路上,而且在網路上包含了使用者的全域設定。儲存在這裡的資料只由目前使用者使用,不管是從網路上的哪台機器登入過來的。
Environment.SpecialFolders.LocalApplicationData返回一個特殊的目錄,該目錄隊了儲存設定資訊以外,同時也是一個使用者的私人目錄,它只屬於從這台機器上登入的使用者。一般GetFolderPath(SpecialFolders.LocalApplicationData)返回:C:\Documents and Settings\<使用者名稱>\Local Settings\Application Data。
這三個不同的位置可以讓你儲存每個人的設定資訊,給定使用者的資訊,或者是給定使用者並給定機器的資訊。具體的使用哪一個取決於應用程式。但考慮一些明顯的例子:資料庫連結字串是一個全域設定,它應該存在在跨平台 app程式資料(Common Application Data) 目錄中。一個使用者的工作內容應該存在在應用程式資料(Application Data)目錄中,因為它只取決於使用者。視窗的位置資訊應該在本地應用程式資料(Local Application Data)目錄中。因為它們取決於機器上的使用者的屬性(不的機器可能有不同的解析度)。
應該有一個特殊的目錄,它為所有應用程式的所有使用者佈建儲存,描述頂層的目錄結構。這裡,你須要在頂層目錄結構下建立子目錄。.Net架構的System.Windows.Application類定義了一些屬性,這些屬性可以為你建立一些通用的配置路徑。Application.LocalAppDataPath屬性返回GetFolderPath(SpecialFolders.CommonApplicationData)+"\\CompanyName\\ProductName\\ProductVersion"的路徑。類似的,Application.UserDataPath和Application.LocalUserDataPath產生位於使用者資料和本機資料目錄下的路徑名,這一目錄包括公司,應用程式,以及版本號碼。如果你組合這些位置,你就可以為你自己公司的所有應用程式建立一個配置資訊,或者為某一程式的所有版本,或者是特殊版本。
注意,這些目錄中我沒有提到過應用程式目錄,就是在Program Files下的目錄。你決不應該在Program Files或者在Windows 系統目錄以及子目錄裡寫資料。這些目錄要更高的特權,因此你並不能指望你的使用者有權利來寫這些資料。
在哪裡儲存應用程式的設定資料已經成為一個很重要的問題,就像每個企業級使用者到家庭使用者所擔心的機器安全問題一樣時,把資訊放在正確的位置就意味著對於使用你的應用程式的使用者來說不用擔心安全問題。你還是要給使用者提供私人的感覺,用.Net的順序組合正確的位置,這樣可以很容易的給每個使用者一種私人的感覺,而且不用折衷安全問題。