C#应用中设计自己的配置文件

原文链接地址: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对象,我们可以增加不限级的子菜单,随意遍历我们的菜单等等。

另,通过这样的方式,可以在我们的应用中设计各种各样易于使用修改和维护的结构。

 

posted @ 2009-04-16 16:05  scgw  阅读(470)  评论(0编辑  收藏  举报