摘要: 本文讨論 My.Settings 類如何使得在Visual Basic 2005 中存儲應用程式和使用者設定變得更為簡單。
注 本文及代碼示例基于 Microsoft Visual Studio 2005 的預釋出版本,其之前的代号為“Whidbey”。文中包含的所有資訊均有可能變更。
本頁内容
簡介 | |
舊方法 | |
新的、更好的方法 | |
進階設定 | |
小結 |
簡介
Windows 窗體應用程式需要運作應用程式所需的資料。多數情況下,您不希望将這一資料包含于代碼中,也不希望在每次進行更改後都重新編譯應用程式。如果您的應用程式 使用 Web 服務或資料庫,則您可能希望将 URL 或連接配接字元串存儲在一個單獨的檔案中,以便可以容易地更改它們。如果應用程式存儲視窗布局和其他 UI 自定義,則需要為每一使用者單獨存儲這一資訊。
過去,此資料存儲在許多不同的位置,如 INI 檔案、系統資料庫或配置檔案中。Microsoft .NET Framework 1.0 引入了 app.config 檔案的概念,這是一些用于存儲此類設定的 XML 檔案。這些方法中的每一種都有一些問題:
• | 設定不是類型安全的。 |
• | 需要相當大數量的編碼(例如用于讀檔案和寫檔案)。 |
• | 系統資料庫方法要求應用程式具有通路系統資料庫的足夠安全權限。 |
• | 很難維護該應用程式的使用者範圍的設定。 |
新 的 Application Settings 體系結構提供了一種将應用程式範圍的設定和使用者範圍的設定均存儲在用戶端上的簡單方式,進而滿足了這些需要。利用 Visual Studio 或一個代碼編輯器,可以指定一個給定屬性的名稱、資料類型、預設值和範圍(應用程式的或使用者的),進而為該屬性定義一個設定。
Application Settings 的工作原理是,根據該設定是應用程式範圍的還是使用者範圍的,将資料以 XML 格式保持到不同的配置 (.config) 檔案。應用程式範圍的設定為隻讀。因為應用程式範圍的設定是程式資訊,是以一般不需要對其進行改寫。相反,即使應用程式是在部分信任的情況下運作,也可以 在運作時安全地讀取和寫入使用者範圍的設定。
傳回頁首
舊方法
.NET Framework 1.0 引入了帶有 app.config 檔案的配置檔案概念。應用程式使用該檔案來存儲特定于應用程式的許多應用程式設定。該檔案是一個簡單的 XML 檔案,您可以很容易地用記事本對其進行編輯,以更改應用程式設定或增加新設定。例如,有很大的空間可以将位址存儲到 SMTP 伺服器、資料庫連接配接字元串,等等。.NET Framework 1.0 實作有幾個缺點。一個缺點是沒有可以寫回檔案的簡單方法。如果您希望通過應用程式中的一個頁面或一個窗體來更改設定,就必須将該檔案作為 XML 檔案加載,加以更改,然後再将其寫回。另一個缺點是通路配置檔案中的屬性不是類型安全的。例如,以下代碼行編譯正常,但如果 PageSize 設定不是整數(非類型安全),則該代碼行就可能導緻運作時錯誤。
Dim PageSize As Integer =
Configuration.ConfigurationSettings.AppSettings("PageSize")
如下所示,沒有什麼可以防止使用者或開發人員将非數字值置于此應用程式設定中,也就不能防止在運作時産生錯誤。
傳回頁首
新的、更好的方法
.NET Framework 2.0 彌補了這些缺點中的大多數,并且還有其他功能。您将注意到的第一點就是,可以很容易地建立一個新設定。不必在打開配置檔案後再輸入新的設定。而是可以進入 項目屬性窗體中的 Settings 設計器,并添加新設定。在這裡可以選擇每個設定的名稱、類型和範圍(應用程式或使用者)。
範圍
應用程式範圍的設定為隻讀,由該應用程式的所有使用者共享。這些設定存儲在<applicationSettings>節的 app.config 檔案中。
注 這不同于上述用在 .NET 1.0 中的<appSettings>節。
在運作時,app.config 檔案将位于 bin 檔案夾中,并以應用程式的名稱命名 (MySettingsDemo.exe.config)。應用程式範圍設定的示例是資料庫連接配接字元串、Web 服務 URL、伺服器的 IP 位址,等等。
<applicationSettings>
<MySettingsDemo.MySettings>
<setting name="SMTPServerIP" serializeAs="String">
<value>127.0.0.1</value>
</setting>
<setting name="MyServicesURL" serializeAs="String">
<value>http://localhost/myservices.asmx</value>
</setting>
</MySettingsDemo.MySettings>
</applicationSettings>
使用者範圍設定特定于每個使用者。可以由應用程式代碼在運作時安全地對其進行讀取和設定。這些設定存儲于一個 user.config 檔案中。為了在技術上準确,每個應用程式中每個使用者有兩個 user.config — 一個用于非漫遊,一個用于漫遊。盡管 Visual Basic 2005 測試版提供的文檔聲明會根據使用者名為 user.config 檔案命名 (joe.config),但實際情況并非如此。此 user.config 檔案建立于 <c:/Documents and Settings>/<username>/[Local Settings/]Application Data/<companyname>/<appdomainname>_<eid>_<hash>/< verison>。其中:
• | <c:/Documents and Settings>為使用者資料檔案夾,或者為非漫遊(以上 Local Settings),或者為漫遊。 | ||||
• | <username>為使用者名。 | ||||
• | <companyname>為 CompanyNameAttribute 值(如果可用)。否則,忽略這一進制素。 | ||||
• | <appdomainname>為 AppDomain.CurrentDomain.FriendlyName。這通常預設為 .exe 名。 | ||||
• | <eid>為 URL、StrongName 或 Path,系基于可用于散列的證據。 | ||||
• | <hash>是從 CurrentDomainis 中收集的證據 SHA1 散列,其優先選擇的順序如下:
| ||||
• | <version>為 AssemblyInfo 的 AssemblyVersionAttribute 設定。 |
示例路徑如下所示:
C:/Documents and Settings/Emad.BROKENOAK/Local Settings/Application
Data/MySettingsDemo/MySettingsDemo_9cfe5ef1/1.0.0.0
此示例路徑打開時類似于圖 1。
圖 1. 示例路徑
注 所顯示和讨論的使用者設定配置檔案的位置對于 Beta 1 版是正确的,但 Visual Basic 2005 最終版本的位置尚未最終确定。
此 user.config 檔案是在一個新使用者第一次運作該應用程式時,并且沒有将非預設值寫入到使用者範圍設定的情況下,于運作時自動建立的。這些設定定義于< userSettings>節下的 app.config 檔案中。設定的預設/初始值也定義于 app.config 檔案中。以下代碼片段顯示了它在 app.config 檔案中的外觀:
<userSettings>
<MySettingsDemo.MySettings>
<setting name="LastSearchedItem" serializeAs="String">
<value />
</setting>
<setting name="FormSize" serializeAs="String">
<value>400, 400</value>
</setting>
<setting name="FormLocation" serializeAs="String">
<value>0, 0</value>
</setting>
</MySettingsDemo.MySettings>
</userSettings>
使用者範圍設定非常适合于存儲應用程式的首選項,這些首選項對于每個使用者來說通常是不同的。使用者範圍設定的示例為顯示設定,例如,字型大小、視窗位置、MRU 清單,等等。
這一體系結構非常靈活,因為即使應用程式運作在部分信任情形中,它也使應用程式能夠為每個使用者存儲設定和首選項。
建立一個設定
假定您的應用程式中有一個搜尋框,而且您希望存儲所搜尋的最後一個項的值。首先,建立應用程式的 UI,如圖 2 所示。
圖 2. 建立搜尋框 UI
現在,為最後搜尋的項的字元串建立設定。所完成的搜尋框與圖 3 相似。
1. | 在解決方案資料總管中,輕按兩下 My Project。 |
2. | 單擊 Settings 頁籤,顯示 Settings Designer。 |
3. | 輸入設定的名稱、類型和範圍(分别為:“LastSearchedItem”、String 和 User)。 |
4. | 在 Value 欄中,輸入這一設定的初始值(希望搜尋什麼?),或者使其保持空白。 圖 3. 完成的搜尋框 |
背景設定
在向 Settings Designer 中添加一個新設定時,在背景會發生幾件事情。首先,向定義各節的 app.config 檔案中添加一個項,以定義設定。
<configSections>
<sectionGroup
name="applicationSettings"type="System.Configuration.ApplicationSettingsGroup, System,
Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="MySettingsDemo.MySettings"
type="System.Configuration.ClientSettingsSection, System,
Version=2.0.3600.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</configSections>
接着,将設定定義本身添加到 app.config 檔案中(如下所示)。根據所定義的設定類型,可以看到一個 applicationSettings、userSettings 和/或 connectionStrings 節(一個或多個),具體看到的内容取決于所定義的是何種設定。
<userSettings>
<MySettingsDemo.MySettings>
<setting name="LastSearchedItem" serializeAs="String">
<value />
</setting>
<setting name="FormSize" serializeAs="String">
<value>400, 400</value>
</setting>
<setting name="FormLocation" serializeAs="String">
<value>0, 0</value>
</setting>
</MySettingsDemo.MySettings>
</userSettings>
<connectionStrings>
<add name="MySettingsDemo.MySettings.ConnectionString"
connectionString="Server=TABLET; User ID=sa; Password=1234;
Database=Northwind; Persist Security Info=True"
providerName="System.Data.SqlClient" />
</connectionStrings>
<applicationSettings>
<MySettingsDemo.MySettings>
<setting name="SMTPServerIP" serializeAs="String">
<value>192.168.2.11</value>
</setting>
<setting name="MyServicesURL" serializeAs="String">
<value>http://localhost/MyServices/Service1.asmx</value>
</setting>
</MySettingsDemo.MySettings>
</applicationSettings>
通路設定
現在已經添了一個設定,需要對其進行檢索和更新。檢索一個設定非常簡單。可以按以下方式對其進行檢索:
My.Settings.LastSearchedItem
圖 4 顯示了如何通過 IntelliSense 通路應用程式的設定字段,進而可以很容易地找到所要用到的精确設定值。
圖 4. 工作中的 IntelliSense 功能
使用設定的另一方法是将其綁定到一個屬性。這幾乎不需要代碼。例如,可以将 FormLocation 設定綁定到窗體的位置屬性。
• | 在該窗體的屬性視窗中,展開 Data | (ApplicationSettings) | (PropertyBinding)。 |
• | 找到 Location 屬性并選擇 FormLocation 設定,如圖 5 所示。 圖 5. 選擇 FormLocation 設定 |
這将在窗體的設計器代碼隐藏類中建立該代碼:
Me.DataBindings.Add(New System.Windows.Forms.Binding("Location",
MySettingsDemo.MySettings.Value, "FormLocation", True,
MySettingsDemo.MySettings.Value.LastSearchedItem, Nothing,
System.Windows.Forms.BindingUpdateMode.OnPropertyChanged))
請注意 Binding 類構造中的最後一個參數。它定義了設定的更新模式。可以根據更改進行更新,可以根據驗證進行更新,也可以從不更新。設計器中所生成的預設代碼根據更改對其進行更新。
在将設定綁定到屬性時,不需要擔心設定的讀取或寫入。在需要該屬性時會自動對其進行設定,而且如果更改了它的值,則會自動儲存它。請注意所有這些工作是如何在無需編寫一行代碼的情況下完成的。
注 這些設定僅自動儲存于某些項目類型中,例如,Visual Basic Windows Forms 應用程式。在其他情況下,例如在 Class Library 項目中,需要顯式調用 My.Settings 類的 Save 方法。
如果該屬性未列于屬性綁定視窗中,仍然可以使用代碼來達到同一目的。由于某種原因,Size 屬性不能用作可綁定的屬性。這是在這一版本中做出的設計決定,但在最終版本中,将會使所有屬性都可用于綁定。這是通過将一個新的 Binding 添加至窗體的 DataBindings 集合中實作的。Binding 類用于定義屬性名、設定名、資料存儲和更新模式。是以,要将大小屬性綁定到 FormSize 設定,可以在窗體加載事件中手動建立該綁定:
Me.DataBindings.Add(New System.Windows.Forms.Binding("Size", _
MySettingsDemo.MySettings.Value, _
"FormSize"))
傳回頁首
進階設定
如果您希望增強對設定的控制,可以定義自己的、派生于 ApplicationSettingsBase(所有設定類的父類)的類。将每個設定定義為一個已經定義了擷取和設定方法的屬性。如果該屬性是應用程式範圍的設定,則使用 ApplicationScopedSettingAttribute 修飾該屬性,如果是使用者範圍的設定,則使用 UserScopedSettingAttribute 修飾它。實際上,這就是設定設計器所做的工作。下面是由設定設計器所生成的 MySettings.vb 檔案中的一個片段:
Partial NotInheritable Class MySettings
Inherits System.Configuration.ApplicationSettingsBase
<System.Diagnostics.DebuggerNonUserCode(), _
System.Configuration.UserScopedSettingAttribute(), _
System.Configuration.DefaultSettingValueAttribute("400, 400")> _
Public Property FormSize() As System.Drawing.Size
Get
Return CType(Me("FormSize"),System.Drawing.Size)
End Get
Set
Me("FormSize") = value
End Set
End Property
<System.Diagnostics.DebuggerNonUserCode(), _
System.Configuration.SpecialSetting(System.Configuration.SpecialSetting.ConnectionString), _
System.Configuration.ApplicationScopedSettingAttribute(), _
System.Configuration.DefaultSettingValueAttribute("Server=TABLET;
User ID=sa; Password=1234; Database=Northwind; Persist Security In"& _
"fo=True")> _
Public ReadOnly Property ConnectionString() As String
Get
Return CType(Me("ConnectionString"),String)
End Get
End Property
<System.Diagnostics.DebuggerNonUserCode(), _
System.Configuration.ApplicationScopedSettingAttribute(), _
System.Configuration.DefaultSettingValueAttribute("192.168.2.11")> _
Public ReadOnly Property SMTPServerIP() As String
Get
Return CType(Me("SMTPServerIP"),String)
End Get
End Property
...
注 連接配接字元串由 SpecialSetting 屬性修飾。它們也是在 onfig 檔案内它們自己的節中建立的。
另請注意,它是一個 Partial 類,這意味着可以在項目中建立另一個檔案,并為該類建立另一個部分。采用這一技術,可以對設定進行微調,而不需要使用設計器所生成的檔案。可以在該類中添加事件處理,以便對設定進行更為準确的控制。可以處理的三個事件為:
• | SettingChanging |
• | SettingsSaving |
• | PropertyChanging |
請注意,這些設定功能位于一個可插接式提供程式基礎結構的頂部,這一點非常重要。目前,Visual Studio 2005 隻包含一個可以通路 .config 檔案的提供程式 — LocalFileSettingsProvider。可以插入備用提供程式,用于代替 Local File Settings Provider,或作為其補充。例如,雲彩場景中的設定,其中 Web 服務用于将設定存儲于一個資料庫中,可以在使用者登入的任何位置擷取設定。
傳回頁首
小結
以 前用于處理應用程式設定的體系結構有一定的限制,.NET Framework 2.0 中的新 Application Settings 體系結構解決了其中的大部分問題。新體系結構極大地簡化了設定的建立、綁定、檢索和更新,如本文借助于 Visual Basic 2005 所做的說明。它還解決了應用程式範圍和使用者範圍的設定。這一新的體系結構必然能夠提高工作效率,使開發人員專心解決業務問題,而不再需要花費幾天、幾周的 時間來指出應用程式設定中的所有症結。