系统配置可以分为好多种,ini的,注册表或者其他的。在TSysConfig中,引用了两个类:TSysIni和TSysReg。前者提供系统的ini配置服务,后者提供系统的注册表配置服务。
private TSysIni FSysIni;
private TSysReg FSysReg;
下面行说Ini服务TSysIni。
这个类需要完成的功能比较简单,它要提供一些系统配置的存取操作。一般来说,写入ini是这样进行的:WriteString(string big,string small,string value),当然,在写入之前,还需要连接ini文件---那么,是否可以让连接ini文件的工作由TSysIni来做,而实际的ini操作功能由其他类来实现呢?答案当然是可以的,请看TSysIni 的构造函数:
public class TSysIni : ieIni.ieIni
...{
/**//// <summary>
/// 在执行完ieIni的构造函数后,给FileName赋值,并连接到ini文件
/// 由于此类用于系统ini配置,因此FileName在构造函数中就被赋值
/// </summary>
public TSysIni()
...{
this.FileName = Application.StartupPath + @"SysConfig.ini";
this.Active = true;
}
}
这里,命名空间ieIni中的类ieIni是我自定义的一个控件,它提供了对ini的读写操作。这样,类TSysIni就只是与SysConfig.ini这个系统配置文件相关。然后,在类TSysConfig中可以以属性的方式将TSysIni的对象公布出来,也可以不用公布TSysIni对象而仅提供一些常用的系统ini配置操作,我用了后面的一种方法:
public void SetIniString(string name, string Value)
...{
FSysIni.SetString("SystemConfig", name, Value);
}
public string GetIniString(string name, string Default)
...{
return FSysIni.GetString("SystemConfig", name, Default);
}
其他还有对bool、DateTime、int、double的操作,与对String的操作非常相似。
可能会问,一个简单的ini操作而已,还需要设计成三个等级的类,也太麻烦了吧!
这样做,当然有原因:
对系统配置类TSysConfig来说,它不需要知道这些配置写入了哪个ini文件,如何写入ini文件,它只需知道通过变量FSysIni就可以将配置写入ini文件。
对类TSysIni,它同样只需知道通过父类ieIni,可以将配置写入SysConfig.ini,至于如何写入由ieIni来关心。
而类ini提供了最基础的ini读写操作。
将各个类的功能划分清楚,可以方便地对各项功能进行扩展:
TSysConfgi还需要系统注册配置服务,好,我们引用类TSysReg,具体如何实现由类TSysReg去关心;
除了系统配置SysConfig.ini,可能还需要其他的配置文件,比如记录各种窗口的大小、位置等,那么我们像类TSysIni一样,建立一个新类TWindowsInfoIni,它可以提供类似于这样的功能:SetWindowInfo(string windowName,Rectangle rect);
ieIni中目前提供了string、int、double、bool、datetime等类型数据的操作,同样可以方便地增加其他数据类型的读写操作。而且它可以很方便地移植到其他项目中。(事实上,类ieIni本来就是从其他项目移植过来的。)
该说ieIni了,毕竟ini操作的主角是它。
使用vs2005,不得不说有时候是比较郁闷的。举个简单的例子,它居然不像dlephi一样,提供类对ini进行读写操作。虽然说提供api调用的方式,但还是显得比较麻烦。在学习ado.net时,我发现了类DataSet的两个方法:WriteXml和ReadXml。于是我就想,何不利用DataSet来间接地实现ini的操作呢?只要是保存到一个ini文件中,调用的方法类似,实际存储的格式并不不重要。何况,xml也是一种趋势!
由于考虑到使用的方便,我将ieIni做成了一个控件:
public partial class ieIni : Component
首先,它需要下面的这些变量(变量的作用见说明):
private DataSet ini = new DataSet("ini");//DataSet对象,通过它间接地实现ini操作
private Boolean FActive = false;//记录是否与ini文件进行操作
private Boolean FUP = true;//FUP表示每次写入数据时,是否要即时更新到ini文件, 默认为即时更新
private string FFileName;//用于保存ini文件名,内部使用
要使用它,第一步便是设置ini文件的路径:
public String FileName
...{
get
...{
return FFileName;
}
set
...{
if (!Active)
...{
FFileName = value;
}
else
...{
System.Windows.Forms.MessageBox.Show("已连接到ini文件,无法设置文件名!");
}
}
}
其中Active是与变量FActive相关的一个属性,通过它来获取或设置与ini文件的连接状态:
public bool Active
...{
get
...{
return FActive;
}
set
...{
if (value)
...{
if (FActive)
return;
连接ini文件#region 连接ini文件
try
...{
ini.ReadXml(FileName);
FActive = true;
}
catch (Exception)
...{
FActive = false;
}
if (!(FActive))
...{
try
...{
string s = Path.GetDirectoryName(FileName);
if (!(Directory.Exists(s)))
Directory.CreateDirectory(s);
ini.WriteXml(FileName);
FActive = true;
}
catch (Exception ex)
...{
System.Windows.Forms.MessageBox.Show(ex.Message);
FActive = false;
}
}
#endregion
}
else
...{
FActive = false;
try
...{
ini.WriteXml(FileName);
}
catch (Exception)
...{
}
ini.Clear();
}
}
}
在设置Active的值为true时,它会检查是否有这个ini文件,没有则建立。
属性UP用于获取或设置变量FUP的值:
public bool UP
...{
get
...{
return FUP;
}
set
...{
FUP = value;
}
}
SetString将一个字符串写入到ini文件中:
public void SetString(string Big, string Small, string Value)
...{
if (!(FActive)) return;
DataTable newTable = ini.Tables[Big];
if (newTable == null)
...{
newTable = new DataTable(Big);
ini.Tables.Add(newTable);
}
DataColumn newColumn = newTable.Columns[Small];
if (newColumn == null)
...{
newColumn = new DataColumn(Small, typeof(string));
newTable.Columns.Add(newColumn);
}
DataRow newRow;
try
...{
newRow = newTable.Rows[0];
}
catch (Exception)
...{
newRow = newTable.NewRow();
newTable.Rows.Add(newRow);
}
try
...{
newRow[Small] = Value;
}
catch (Exception)
...{
}
if (UP) ini.WriteXml(FileName);
}
GetString用于读取一个字符串变量:
public string GetString(string Big, string Small, string Default)
...{
if (!(FActive)) return Default;
string s;
DataTable newTable = ini.Tables[Big];
if (newTable == null)
...{
s = Default;
goto OnGetString;
}
DataColumn newColumn = newTable.Columns[Small];
if (newColumn == null)
...{
s = Default;
goto OnGetString;
}
try
...{
s = newTable.Rows[0][Small].ToString();
}
catch (Exception)
...{
s = Default;
}
}
这两个函数的实现非常简单,这里不多做解释。(原理是将tableName作为ini中的big项,fieldName作为ini中的small项。)
对于其他数据类型的读写操作,可以通过与字符串的转换来进行,就像GetInt一样:
public int GetInt(string Big, string Small, int Default)
...{
string s = GetString(Big, Small, Convert.ToString(Default));
try
...{
return Convert.ToInt32(s);
}
catch (Exception)
...{
return Default;
}
}
最后,由于ieIni是作为控件存在,因此它提供了两个事件,OnSetValue和OnGetValue。关于如何为控件添加事件,不在本章的讨论之列,有兴趣可以自选参考源代码。
由于MyLog3中最后并不需要系统注册表配置服务,所以这里TSysReg我只是定义了一个类的原型,没有任何的实现,留待以后需要的时候再去实现它。
下一篇,系统文件类型注册。
ie.2008-04-07