我們經常會需要在應用程式中宣告一些參數,好讓我們的程式在不用重新編譯的情況下隨時變更參數設定值,而這樣的機制老早就內建在 .NET 之中。今天我將分享幾個常見的使用案例與範例程式,教大家如何規劃 C# 類別庫 (Class Library) 的設定檔,以及如何從 ASP.NET 應用程式 ( 包含 Web Form 與 MVC )、主控台應用程式 (Console Appliation) 與 Windows Form 應用程式正確設定 app.config 或 web.config 設定檔,以變更類別庫中參數的預設值。
讀取 web.config 設定檔的 AppSettings 與 ConnectionStrings 參數
如果你的 C# 類別庫 (Class Library) 所讀取的參數來源只有 ASP.NET 應用程式的話,那麼你可以參考以下說明進行設定。
我們先建立兩個預設專案,一個是 ASP.NET MVC 專案 ( WebApplication1 ),另一個是類別庫專案 ( ClassLibrary1 )。

假設我們希望 ClassLibrary1 類別庫專案可以讀取 WebApplication1 專案中 Web.config 裡面的 appSettings 設定值,這裡我們就以 ClientValidationEnabled 參數為例,如下圖示:

接著,如果我們直接引用 System.Configuration 命名空間,你可以從該命名空間下取得 ConfigurationSettings 類別,並透過該類別取用 AppSettings 屬性,這個屬性是一個字典型別,主要就是用來讀取 Web.config 設定檔中的 <appSettings> 參數資料。

不過,你可以發現到上圖第 17 行有個警告訊息,從「錯誤視窗」中可以看到以下錯誤:
警告 1 'System.Configuration.ConfigurationSettings.AppSettings' 已過時: 'This method is obsolete, it has been replaced by System.Configuration!System.Configuration.ConfigurationManager.AppSettings' G:\Projects\WebApplication1\ClassLibrary1\Class1.cs 16 44 ClassLibrary1
從錯誤訊息可能不太容易看出問題在哪,這個錯誤其實是說 System.Configuration.ConfigurationSettings.AppSettings 已經過時了,不建議在使用,若要使用,請改用 System.Configuration.ConfigurationManager.AppSettings 這個屬性來取得應用程式設定值。不過你在修改的時候將會發現,其實你找不到 ConfigurationManager 這個類別!

這個問題很常見,幾乎每個初學者都會遇到過一次。那是因為預設的主控台應用程式專案或類別庫專案,預設並沒有加入 System.Configuration.dll 的組件參考,因此找不到這個類別。你只要手動加入參考問題即可迎刃而解。


所以只要在加入參考之後,就可以順利找到 ConfigurationManager 類別,並且順利取用 AppSettings 與 ConnectionStrings 屬性以讀取 web.config 設定檔中的參數值。

在 ASP.NET 應用程式裡的 web.config 設定類別庫中定義的參數
這是一個反過來的設定。
也就是你先在類別庫中先預設好參數名稱與值,然後再將類別庫中的參數設定移到 ASP.NET 應用程式的 Web.config 設定檔裡。
這種設定方法有個好處,就是你在類別庫專案中可以利用 Visual Studio 幫你管理參數,至少有個視覺化的工具可用,管理上比較方便。另一個優點則是,你可以在程式碼中使用「強型別」的方式存取參數。
我們先來看看如何在類別庫中定義應用程式參數:
1. 開啟專案屬性

2. 切換到「設定」頁籤,並點擊如下圖編號 3 的連結,自動建立資源檔。

3. 建立後,你可以設定好參數名稱、類型、範圍與值,並且設定整份設定資源檔的存取修飾詞 (Public, Internal),若點擊「檢視程式碼」則可以透過部分類別擴充這份設定資源檔。

當你點下「檢視程式碼」, Visual Studio 會自動幫你在類別庫專案根目錄下建立一個 Settings.cs 檔案,從該檔案你可以看出這是一份 部分類別 (Partial class),並讓你可以設定一些參數變更與儲存的相關事件 (events)。

而這份由 Visual Studio 幫你建立的 設定資源檔 就是類別庫專案的 Properties\Settings.settings 與 Properties\Settings.Designer.cs 這兩個檔案。

Properties\Settings.settings 是個 XML 定義檔,如果你查看專案項目屬性,可以發現他有設定「自訂工具 (Custom Tool)」,這個 SettingsSingleFileGenerator 是一個程式碼產生器,他會自動幫你產生 Properties\Settings.Designer.cs 這個 C# 類別檔,所以請千萬不要手動去修改 Properties\Settings.Designer.cs 檔案的內容。

我們也可以看看這個 Properties\Settings.Designer.cs 檔案的內容,你會發現這個檔案類別名稱固定為 Settings 並且位於 ClassLibraray1.Properties 命名空間下,該類別裡面有實作獨體模式 (Singleton Pattern),讓你可以直接透過 Settings.Defaults 取用這個類別的預設實體 (instance),並且會把你在 [專案屬性] –> [設定] 加入的每個參數都建立起一組屬性名稱,你所設定的型別也都會反映到這個類別中,包含你在 Visual Studio 中設定的預設值,也會透過 DefaultSettingValueAttribute 屬性設定上去。

使用參數時,就可以用強型別的方式取用參數,就算執行時期讀不到相對應的設定參數,至少還會讀取原本在類別庫中設定好的預設值,使用上非常方便!

而建立這份設定資源檔的過程,也會產生一個 app.config 檔案:

這份設定檔的內容,就是標準的 .NET 設定檔格式,其格式與 Web.config 設定檔相容。
簡單來說,你從類別庫專案中設定的那些參數,都會以這種格式進行定義,這裡的 configSections 定義了有哪些 區段 (section) 可以在這份 config 檔使用,他先在這裡設定了 applicationSettings 區段群組 (sectionGroup),所以你才可以在設定檔下方使用 <applicationSettings> 的區段標籤。而在這個 applicationSettings 區段群組 (sectionGroup) 下又設定了一組 ClassLibrary1.Properties.Settings 區段 (section),讓你設定目前這個類別庫專案的所有參數設定。

上述這份設定檔,如果要整合進 ASP.NET 應用程式專案的 Web.config 設定檔裡,你只要分別將 <configSections> 底下的內容套用到 Web.config 裡面,再將整塊 <applicationSettings> 的區段群組移過去即可。

在 Console 主控台應用程式裡的 app.config 設定類別庫中定義的參數
由於預設透過 Visual Studio 建立的專案範本中並沒有 app.config 檔案

你可以直接複製 ClassLibrary1 專案下的 app.config 過來即可。或也可以自己手動新增一個「應用程式組態檔」。


將 ClassLibrary1 的設定值複製過來的結果如下:

若假設你有兩個不同的類別庫,假設第二個類別庫專案叫做 ClassLibrary2 的話,若要將個別類別庫的參數設定加入 App.config 或 Web.config 時,兩個設定檔整合在一起的範例如下圖示,其實就只是把 ClassLibrary2.Properties.Settings 的區段定義,與該區段的參數定義整合到 <applicationSettings> 區段群組下即可:

結語
本篇文章介紹了 .NET 基本的參數設定與使用方式,我大致提到實務上會用到的三種讀取方式 (嚴格說起來只能算兩種):
- 讀取 web.config 設定檔的 AppSettings 與 ConnectionStrings 參數
- 在 ASP.NET 應用程式裡的 web.config 設定類別庫中定義的參數
- 在 Console 主控台應用程式裡的 app.config 設定類別庫中定義的參數
第 1 種,是假設你已經知道目前類別庫會用到 ASP.NET 應用程式中的特定參數,因此你可以直接透過 ConfigurationManager 類別存取 appSettings 與 connectionStrings 的參數值。
第 2 或第 3 種,是完全以類別庫為中心思考,所有參數的定義與管理都在類別庫中完成,其他要使用此類別庫的應用程式,必須配合修改自己的設定檔,將類別庫裡定義的區段設定 (configSection) 手動加入到 app.config 或 web.config 之中。
相關連結