原文連結地址:http://www.wewill.cn/n21188c66.aspx
在系統開發的過程中,我們總是需要使用設定檔來儲存一些我們需要儲存的系統參數,畢竟這是.Net時代,如果再使用註冊表那就顯得複雜了,畢竟操作註冊表的API並不是哪麼容易理解的。
所以在.net應用程式中,都預設出現一個App.Config(對於 Web應用程式是Web.Config)我們可以將系統運行所需要的參數採用加密或者明文的方式儲存在這個檔案中。但是當我們需要大量的,並且有一定邏輯結構的資料,希望也能夠儲存到設定檔中,此時我們可能這樣做:將這些資料構造成DataSet,然後使用DataSet.WriteXML直接寫成XML檔案,讀取的時候直接使用DataSet.LoadXML。另外一種方式就是直接操作XML資料,使用XmlDocument。
第一種方法雖然是好,因為我們可以想操作資料庫表一樣操作我們的結構化的資料,可是在某些情況下,總覺得怪怪的。並且增加列等等這些的操作覺得及其難受。特別是我們需要使用這些資料的時候,我們首先要去讀文檔,瞭解DataSet中的每個表以及每個欄位的含義,所以此方法不可取。
那第二種方法呢,這個更不可取。如果我們增加了某個欄位,或者修改了資料的機構,那我們的代碼修改起來是在也是比較複雜的事情。
那有什麼更好的方式來解決這個問題的呢?
既然微軟可以使用App.Config和Web.Config,可以使用ComfigManager來對這兩個設定檔來進行管理,讓我們非常方便地進行使用,那我們為何不可設計自己的ConfigManager呢?
需求:我們這裡以菜單結構作為例子來描述我們的想法。
菜單,包括主功能表項目,比如系統裡面的“檔案”,“編輯”等等,包括子功能表,比如“檔案”下的“儲存”,“另存新檔”等,子功能表下也包括下級子功能表。總之這是一個完全結構化的資料格式,當然使用菜單來舉例主要是這東西我們每天都見到,所以很容易理解,如:
public class Menu
{
private string _Name;
private string _Text;
private string _IconName;
//...這裡可能還有其他你需要變數
private SubMenus _SubMenus;
/// <summary>
/// 注意,一定需要一個無參數的建構函式,否則序列化的時候出錯
/// </summary>
public Menu()
: this("", "", "")
{ }
public Menu(string name, string text, string iconname)
{
this._Name = name;
this._Text = text;
this._IconName = iconname;
this._SubMenus = new SubMenus();
}
/// <summary>
/// 菜單名
/// </summary>
[XmlAttribute("Name")]
public string Name
{
get { return this._Name; }
set { this._Name = value; }
}
/// <summary>
/// 菜單Text
/// </summary>
[XmlAttribute("Text")]
public string Text
{
get { return this._Text; }
set { this._Text = value; }
}
/// <summary>
/// 菜單的表徵圖名
/// </summary>
[XmlAttribute("IconName")]
public string IconName
{
get { return this._IconName; }
set { this._IconName = value; }
}
/// <summary>
/// 子功能表
/// </summary>
public SubMenus SubMenus
{
get { return this._SubMenus; }
set { this._SubMenus = value; }
}
}
好,那我們功能表項目包括子功能表,怎麼表示呢?
我們使用一個List來儲存我們的子功能表,為了更為直觀,我們定義一個SubMenus的類,繼承於List<Menu>
/// <summary>
/// 子功能表列表
/// </summary>
public class SubMenus : List<Menu>
{
}
下面我們就來構造我們的菜單MenuStrip。一個MenuStrip中,同樣包括多個菜單,比如“檔案”“編輯”“視圖”等等。
在MenuStrip中,我們提供Load()函數,用於載入我們的菜單資料,提供Save()用於儲存我們設定好的菜單資料:
public class MenuStrip
{
//...您需要的其他變數
private SubMenus _SubMenus;
public MenuStrip()
{
this._SubMenus = new SubMenus();
}
public SubMenus SubMenus
{
get { return this._SubMenus; }
set { this._SubMenus = value; }
}
/// <summary>
/// 這裡使用Static,方便調用
/// </summary>
/// <returns></returns>
public MenuStrip Load()
{
MenuStrip instance = new MenuStrip();
XmlSerializer xs = new XmlSerializer(typeof(MenuStrip));
StreamReader sr = new StreamReader(@"...\Menu.Config");
instance = xs.Deserialize(sr) as MenuStrip;
sr.Close();
return instance;
}
public void Save()
{
XmlSerializer xs = new XmlSerializer(typeof(MenuStrip));
StreamWriter sw = new StreamWriter(@"...\Menu.Config");
xs.Serialize(sw, this);
sw.Close();
}
}
測試代碼如下:
MenuStrip menustrip = new MenuStrip();
//檔案菜單
Menu mnuFile = new Menu("mnuFile", "檔案(&F)", "");
mnuFile.SubMenus.Add(new Menu("mnuNew", "建立", ""));
mnuFile.SubMenus.Add(new Menu("mnuSave", "儲存", ""));
mnuFile.SubMenus.Add(new Menu("mnuSaveAs", "另存新檔", ""));
menustrip.SubMenus.Add(mnuFile);
Menu mnuEdit = new Menu("mnuEdit", "編輯(&E)", "");
mnuEdit.SubMenus.Add(new Menu("mnuCopy", "複製", ""));
mnuEdit.SubMenus.Add(new Menu("mnuDelete", "刪除", ""));
mnuEdit.SubMenus.Add(new Menu("mnuCut", "剪下", ""));
menustrip.SubMenus.Add(mnuEdit);
menustrip.SubMenus.Add(new Menu("mnuView", "視圖(&V)", ""));
menustrip.Save();
上面的代碼構造了一個設定檔,儲存後結果如下:
<?xml version="1.0" encoding="utf-8"?>
<MenuStrip xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SubMenus>
<Menu Name="mnuFile" Text="檔案(&F)" IconName="">
<SubMenus>
<Menu Name="mnuNew" Text="建立" IconName="">
<SubMenus />
</Menu>
<Menu Name="mnuSave" Text="儲存" IconName="">
<SubMenus />
</Menu>
<Menu Name="mnuSaveAs" Text="另存新檔" IconName="">
<SubMenus />
</Menu>
</SubMenus>
</Menu>
<Menu Name="mnuEdit" Text="編輯(&E)" IconName="">
<SubMenus>
<Menu Name="mnuCopy" Text="複製" IconName="">
<SubMenus />
</Menu>
<Menu Name="mnuDelete" Text="刪除" IconName="">
<SubMenus />
</Menu>
<Menu Name="mnuCut" Text="剪下" IconName="">
<SubMenus />
</Menu>
</SubMenus>
</Menu>
<Menu Name="mnuView" Text="視圖(&V)" IconName="">
<SubMenus />
</Menu>
</SubMenus>
</MenuStrip>
您可能會說,這樣也不見得很好啊,但是你是否發現,我們就像使用菜單對象一樣來操作我們的Menu對象,我們不需要像使用DataSet那樣首先要去瞭解其中每個資料庫表的每個欄位的含義,也不需要像使用XmlDocument那樣去記住每個功能表項目的位置。功能表項目就是我們的Menu對象,我們可以增加不限級的子功能表,隨意遍曆我們的菜單等等。
另,通過這樣的方式,可以在我們的應用中設計各種各樣便於使用修改和維護的結構。