淺談config文件的使用


一、緣起


    最近做項目開始使用C#,因為以前一直使用的是C++,因此面向對象思想方面的知識還是比較全面的,反而是因沒有經過完整、系統的.Net方面知識的系統學習,經常被一些在C#老鳥眼里幾乎是常識的小知識點給絆倒。

 

    為什么這么說呢,因為我在網絡上查找的資料的時候,經常大部分問題,都是能夠找到或多或少的參考資料,但是這些小知識點卻很少能夠找到正確的解決方法,有也是只有提問,沒有回到,那么這種情況出現,就只有2種解釋:
1、這個方面的問題很難,難到沒有人能夠解決;
2、這個問題太簡單,簡單到稍微熟悉的人都不屑於回答,提問者也在一番思考后,輕松找到答案。(我比較傾向這個,呵呵,因此我也把這些小知識,叫做:容易被忽略的細節)

 

    然而,無論問題是否簡單,既然我會被絆倒,耽擱時間,肯定也會有人被同樣耽擱,因此我想把這些細節整理出來,還是具有一定意義的。

 

    於是,本系列文章開始...


二、問題描述


    除了正常情況下的config文件,使用ConfigurationManager加載,我們還可能會碰到一下這樣的情況:
1、加載非當前應用程序yyy.exe默認的config文件的xxx.exe.config文件;(比如:與yyy.exe.config不在同一目錄下 或者 文件名不同)
2、加載非應用程序的xxx.config文件;
3、讓類庫xxx.dll內的函數讀取默認config文件的時候,讀取的是xxx.dll同級目錄下的xxx.dll.config文件,而不是加載xxx.dll的應用程序yyy.exe的默認應用程序配置文件:yyy.exe.config;
    以上三種情況,都不能直接使用ConfigurationManager來加載

 

三、解決過程


    讓我們從最基礎、最簡單、最常見的config文件的加載來入手,解決上面三個問題:

 

step1:研究基礎的config文件加載

    config文件,是給客戶端應用程序保存配置信息用的,一般情況,一個應用程序只會有一個這樣的文件,在編譯之前,叫做App.config,每次使用Visual Studio編譯,都會Copy到應用程序的生成目錄,且Rename為:應用程序名.config。
    要讀取config文件內的信息,只需要使用ConfigurationManager的相關函數和屬性即可,因此我們來研究下ConfigurationManager,看看是否能找到解決問題的相關信息。
打開MSDN,找到這樣一個方法:

OpenExeConfiguration  已重載。 將指定的客戶端配置文件作為 Configuration 對象打開。

    OK,要找的就是這個,因為這個方法有一個重載方法是:

OpenExeConfiguration(String)  將指定的客戶端配置文件作為 Configuration 對象打開。

 

step2:加載非當前應用程序默認的config文件

    於是,第一個問題的解決方案,似乎、應該、可能找到了,按照MSDN上的說明,若我們把要打開的xxx.exe.config的路徑作為參數傳入即可,代碼如下:

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe.config");
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    但是,事情並沒有這么順利,這樣是無法打開xxx.exe.config文件的,經過調試,發現:config的屬性FilePath的值為:"C:\\xxx.exe.config.config",程序自己在傳入的參數后增加了“.config”作為要打開的config文件的路徑,這顯然和我們之前從MSDN上所看到的不一樣,不用說,我們被微軟小小的耍了一把。這里要傳入的參數,不應該是要打開的config的路徑,而應該是這個config文件對應的應用程序的路徑,也就是說上面的代碼應該這樣寫:

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx.exe"); // 寫的是應用程序的路徑
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    再次運行,呵呵,還是不行,提示錯誤:『加載配置文件時出錯: 參數“exePath”無效。參數名: exePath』。顯然我們有被耍了,這里要傳入應用程序路徑(exePath)沒錯,但是因為我們並沒有在xxx.exe.config文件同目錄下,加入xxx.exe文件,因此我們傳入的exePath實際上是無效的,可見為了能夠加載xxx.exe.config,我們弄一個xxx.exe文件放在一起。

    ok,運行,成功。

    小結1:第一個問題的解決方案找到:

使用ConfigurationManager.OpenExeConfiguration(string exePath)即可,同時注意2個小細節:
A:改方法需傳入的是exePath,而不是configPath;
B:exePath必須是有效的,因此xxx.exe和xxx.exe.config應該成對出現,缺一不可。

 

step3:擴展step2的戰果,找到加載xxx.config的方法

    step2已經找到了加載xxx.exe.config的方法,觀察xxx.exe.config的名稱,發現,若把xxx.exe看成YYY,顯然xxx.exe.config = YYY.config,也就是說:xxx.exe.config是xxx.config中比較特殊的一種,他要求config文件的文件名最后4個字母必須是“.exe”。

    此時,大膽推測,使用ConfigurationManager.OpenExeConfiguration(string exePath),應該可以解決問題。

   Configuration config = ConfigurationManager.OpenExeConfiguration("C:\\xxx"); // 記得要有xxx文件,否則這個路徑就是無效的了。
   DllInfo dllInfo = config.GetSection("DllInfo") as DllInfo;
   Console.WriteLine(dllInfo);

    運行,HOHO,成功了。

    小結2:第二個問題和第一個問題的解決方案一樣。

 

step4:擴展xxx.config解決問題3

    繼續擴大戰果,還是從文件名上來找思路,我們要加載的xxx.dll.config,其實也是xxx.config中稍微特殊的一種,顯然也可以和step3那樣處理。

    使用OpenExeConfiguration(string exePath)來解決問題三,在dll內,碰到需要讀取config文件信息的時候,放棄使用ConfigurationManager的函數或屬性直接獲取,而改用OpenExeConfiguration(string exePath)加載config文件為一個Configuration對象的對應函數或屬性即可。

    小結3:第三個問題同樣可以按照第一個問題的方案來做。

 

四、額外的思考

    在應用程序yyy.exe中通過ConfigurationManager可以很方便的讀取到yyy.exe.config文件中的信息,但在類庫中使用ConfigruationManager讀取的卻不是自動編譯生成的xxx.dll.cofig文件,而是引用類庫的應用程序yyy.exe的yyy.exe.config文件。

 

    有沒有什么辦法,讓類庫中的ConfigurationManager讀取的也是他默認的xxx.dll.config文件呢?

 

    其實,是可以的,不過這里涉及到了應用程序域(AppDomain)的概念, .Net上的應用程序都是運行在一個應用程序域(AppDomain)內的,在程序啟動之初,都會默認啟動一個AppDomain,查看MSDN可以看到AppDomain有一個屬性:SetupInformation,這個屬性保存的就是當前域的config文件路徑;可惜,這個屬性是只讀的,所以我們默認AppDomain的config文件路徑。

 

    因此,若想讓類庫能夠直接使用ConfigurationManager來讀取自己默認的config文件,就只能把類庫放在一個新的AppDomain中執行,並且在創建AppDomain的時候指定他的SetupInformation為類庫默認的config文件路徑;AppDomain有一個用來創建新AppDomain的方法:CreateDomain(String, Evidence, AppDomainSetup);只要把第三個參數的屬性ConfigurationFile只想類庫默認的config文件路徑即可。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM