Discuz!NT之配置文件类[discuz.config]
如果大家从官方下载2.0正式版的DLL程序集中会从里面找到discuz.config这个DLL文件。通过
reflector 反射加载这个程序集后,后从中找到一些从类名称上非常相似且有一定规律(格式)的类。
它们是:
全局配置类
GeneralConfigFileManager.cs
GeneralConfigInfo.cs
GeneralConfigs.cs
Emial配置类
EmailConfigFileManager.cs
EmailConfigInfo.cs
EmailConfigs.cs
基本配置类
BaseConfigFileManager.cs
BaseConfigInfo.cs
BaseConfigInfoCollection.cs
BaseConfigs.cs
相册配置类
AlbumConfigFileManager.cs
AlbumConfigInfo.cs
AlbumConfigs.cs
聚合配置类
AggregationConfig.cs
AggregationConfigFileManager.cs
AggregationConfigInfo.cs
空间开通配置类
SpaceActiveConfigs.cs
SpaceActiveConfigFileManager.cs
SpaceActiveConfigInfo.cs.cs
可以看到,这些类基本上是以三个一组,共六组。而这六组类中的...FileManager.cs与Defau-
ltConfigFileManager.cs的关系如下图所示:
从类图上看,DefaultConfigFileManager.cs是基类,而GeneralConfigFileManager.cs,Emai-
lConfigFileManager.cs,BaseConfigFileManager.cs,AlbumConfigFileManager.cs,Aggregatio-
nConfigFileManager.cs, SpaceActiveConfigFileManager.cs分别派生自DefaultConfigFileManager。
而DefaultConfigFileManager本身也定义了几个属性和方法以便于子类调用或重写(如SaveConfig)。
而DefaultConfigFileManager的定义如下:
/// <summary>2
/// 文件配置管理基类3
/// </summary>4
public class DefaultConfigFileManager5
{6
/// <summary>7
/// 文件所在路径变量8
/// </summary>9
private static string m_configfilepath;10

11
/// <summary>12
/// 临时配置对象变量13
/// </summary>14
private static IConfigInfo m_configinfo = null;15

16
/// <summary>17
/// 锁对象18
/// </summary>19
private static object m_lockHelper = new object();20
21

22
/// <summary>23
/// 文件所在路径24
/// </summary>25
public static string ConfigFilePath26
{27
get { return m_configfilepath; }28
set { m_configfilepath = value; }29
}30

31
32
/// <summary>33
/// 临时配置对象34
/// </summary>35
public static IConfigInfo ConfigInfo36
{37
get { return m_configinfo; }38
set { m_configinfo = value; }39
}40
41
/// <summary>42
/// 加载(反序列化)指定对象类型的配置对象43
/// </summary>44
/// <param name="fileoldchange">文件加载时间</param>45
/// <param name="configFilePath">配置文件所在路径</param>46
/// <param name="configinfo">相应的变量 注:该参数主要用于设置m_configinfo变量和获取类型.GetType()</param>47
/// <returns></returns>48
protected static IConfigInfo LoadConfig(ref DateTime fileoldchange, string configFilePath, IConfigInfo configinfo)49
{50
return LoadConfig(ref fileoldchange, configFilePath, configinfo, true);51
}52

53

54
/// <summary>55
/// 加载(反序列化)指定对象类型的配置对象56
/// </summary>57
/// <param name="fileoldchange">文件加载时间</param>58
/// <param name="configFilePath">配置文件所在路径(包括文件名)</param>59
/// <param name="configinfo">相应的变量 注:该参数主要用于设置m_configinfo变量 和 获取类型.GetType()</param>60
/// <param name="checkTime">是否检查并更新传递进来的"文件加载时间"变量</param>61
/// <returns></returns>62
protected static IConfigInfo LoadConfig(ref DateTime fileoldchange, string configFilePath, IConfigInfo configinfo, bool checkTime)63
{64
m_configfilepath = configFilePath;65
m_configinfo = configinfo;66

67
if (checkTime)68
{69
DateTime m_filenewchange = System.IO.File.GetLastWriteTime(configFilePath);70

71
//当程序运行中config文件发生变化时则对config重新赋值72
if (fileoldchange != m_filenewchange)73
{74
fileoldchange = m_filenewchange;75
lock (m_lockHelper)76
{77
m_configinfo = DeserializeInfo(configFilePath, configinfo.GetType());78
}79
}80
}81
else82
{83
lock (m_lockHelper)84
{85
m_configinfo = DeserializeInfo(configFilePath, configinfo.GetType());86
}87
88
}89
90

91
return m_configinfo;92
}93

94

95
/// <summary>96
/// 反序列化指定的类97
/// </summary>98
/// <param name="configfilepath">config 文件的路径</param>99
/// <param name="configtype">相应的类型</param>100
/// <returns></returns>101
public static IConfigInfo DeserializeInfo(string configfilepath, Type configtype)102
{103

104
IConfigInfo iconfiginfo;105
FileStream fs = null;106
try107
{108
fs = new FileStream(configfilepath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);109
XmlSerializer serializer = new XmlSerializer(configtype);110
iconfiginfo = (IConfigInfo)serializer.Deserialize(fs);111
}112
catch (Exception ex)113
{114
throw ex;115
}116
finally117
{118
if (fs != null)119
{120
fs.Close();121
}122
}123

124
return iconfiginfo;125
}126

127

128
public virtual bool SaveConfig()129
{130
return true;131
}132

133
/// <summary>134
/// 保存(序列化)指定路径下的配置文件135
/// </summary>136
/// <param name="configFilePath">指定的配置文件所在的路径(包括文件名)</param>137
/// <param name="configinfo">被保存(序列化)的对象</param>138
/// <returns></returns>139
public bool SaveConfig(string configFilePath, IConfigInfo configinfo)140
{141
bool succeed = false;142
FileStream fs = null;143
try144
{145
fs = new FileStream(configFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);146
XmlSerializer serializer = new XmlSerializer(configinfo.GetType());147
serializer.Serialize(fs, configinfo);148
//成功则将会返回true149
succeed = true;150
}151
catch (Exception ex)152
{153
throw ex;154
}155
finally156
{157
if (fs != null)158
{159
fs.Close();160
}161
}162

163
return succeed;164
}165
}166

167

如果您一直关注我们的这个产品,就会从中发现在1.0正式版时,这些类(或实现这些功能的类)
还是零星分面在discuz.forum和discuz.forumpage(2.0正式版改名为discuz.web.dll)等几个DLL文件
中。后来因为考虑软件架构和出于统一配置管理的需求,产品小组将这些类重构到了discuz.config,
从此这些类有了一个“新家”。
为了便于开发和统一接口调用,我们又创建了两个接口类,就是IConfigFileManager.cs,ICon-
figInfo.cs,它们的声明如下(相关说明见注释):
IConfigFileManager.cs
/// <summary>2
/// Discuz!NT 配置管理类接口3
/// </summary>4
public interface IConfigFileManager5
{6
/// <summary>7
/// 加载配置文件8
/// </summary>9
/// <returns></returns>10
IConfigInfo LoadConfig();11

12

13
/// <summary>14
/// 保存配置文件15
/// </summary>16
/// <returns></returns>17
bool SaveConfig();18
}19

20

IConfigInfo.cs
/// <summary>2
/// Discuz!NT 配置信息类接口3
/// </summary>4
public interface IConfigInfo5
{6
}7

大家可以看到,其中的 IConfigInfo接口没有任何属性和方法,是一个“空接口”,这主要是为
了提供统一的向上转型需要。当然,如果以后有需要还是会添加一些方法和属性的。
为了减少篇幅,下面只对其中的 GeneralConfig进行相应介绍,一是因为它是核心的配置类,有
关它的使用在项目中不胜枚举。另外它也是这个项目中比较标准的“宝贝”,从一开始,只要有新的
功能往往都会对这个配置类有所“关照”。下面就是通过反射后得到的代码,相关的说明见注释即可:
论坛全局配置管理类(GeneralConfigFileManager):
/// <summary>2
/// 全局配置设置管理类3
/// </summary>4
class GeneralConfigFileManager : Discuz.Config.DefaultConfigFileManager5
{6
private static GeneralConfigInfo m_configinfo;7

8
9
/// <summary>10
/// 文件修改时间11
/// </summary>12
private static DateTime m_fileoldchange;13

14

15
/// <summary>16
/// 初始化文件修改时间和对象实例17
/// </summary>18
static GeneralConfigFileManager()19
{20
m_fileoldchange = System.IO.File.GetLastWriteTime(ConfigFilePath);21

22
try23
{24
m_configinfo = (GeneralConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(GeneralConfigInfo));25
}26
catch27
{28
if (File.Exists(ConfigFilePath))29
{30
ReviseConfig();31
m_configinfo = (GeneralConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(GeneralConfigInfo));32
}33
}34
}35

36
public new static IConfigInfo ConfigInfo37
{38
get { return m_configinfo; }39
set { m_configinfo = (GeneralConfigInfo) value; }40
}41

42
/// <summary>43
/// 配置文件所在路径44
/// </summary>45
public static string filename = null;46

47

48
/// <summary>49
/// 获取配置文件所在路径50
/// </summary>51
public new static string ConfigFilePath52
{53
get54
{55
if (filename == null)56
{57
filename = Utils.GetMapPath(BaseConfigs.GetForumPath + "config/general.config");58
}59

60
return filename;61
}62

63
}64

65
/// <summary>66
/// 返回配置类实例67
/// </summary>68
/// <returns></returns>69
public static GeneralConfigInfo LoadConfig()70
{71

72
try73
{74
ConfigInfo = DefaultConfigFileManager.LoadConfig(ref m_fileoldchange, ConfigFilePath, ConfigInfo, true);75
}76
catch77
{78
ReviseConfig();79
ConfigInfo = DefaultConfigFileManager.LoadConfig(ref m_fileoldchange, ConfigFilePath, ConfigInfo, true);80
}81
return ConfigInfo as GeneralConfigInfo;82
}83

84
/// <summary>85
/// 保存配置类实例86
/// </summary>87
/// <returns></returns>88
public override bool SaveConfig()89
{90
return base.SaveConfig(ConfigFilePath, ConfigInfo);91
}92

93

论坛全局配置描述类(GeneralConfigInfo):
论坛全局配置类(GeneralConfigs):
/// <summary>2
/// 论坛全局配置类3
/// </summary>4
public class GeneralConfigs5
{6
private static object lockHelper = new object();7

8
private static System.Timers.Timer generalConfigTimer = new System.Timers.Timer(15000);9

10
private static GeneralConfigInfo m_configinfo;11

12
/// <summary>13
/// 静态构造函数初始化相应实例和定时器14
/// </summary>15
static GeneralConfigs()16
{17
m_configinfo = GeneralConfigFileManager.LoadConfig();18

19
generalConfigTimer.AutoReset = true;20
generalConfigTimer.Enabled = true;21
generalConfigTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);22
generalConfigTimer.Start();23
}24

25
private static void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)26
{27
ResetConfig();28
}29

30

31
/// <summary>32
/// 重设配置类实例33
/// </summary>34
public static void ResetConfig()35
{36
m_configinfo = GeneralConfigFileManager.LoadConfig();37
}38

39
public static GeneralConfigInfo GetConfig()40
{41
return m_configinfo;42
}43

44
45

46
/// <summary>47
/// 获取默认模板id48
/// </summary>49
/// <returns></returns>50
public static int GetDefaultTemplateID()51
{52
return GetConfig().Templateid;53
}54

55
56

57
/// <summary>58
/// 获得设置项信息59
/// </summary>60
/// <returns>设置项</returns>61
public static bool SetIpDenyAccess(string denyipaccess)62
{63
bool result;64
65
lock(lockHelper) 66
{67
try68
{69
GeneralConfigInfo configInfo = GeneralConfigs.GetConfig();70
configInfo.Ipdenyaccess = configInfo.Ipdenyaccess + "\n" + denyipaccess;71
GeneralConfigs.Serialiaze(configInfo, Utils.GetMapPath(BaseConfigs.GetForumPath + "config/general.config"));72
result = true;73
}74
catch75
{76
return false;77
}78
79
}80
return result;81

82
}83

84

85
Helper108
}109

110

通过对general系列配置类的介绍,再看其它的配置类会很清楚了。这里就不再多做解释了,相信2.0开源后
大家看到源码和注释后会有所感悟的。
另外就是之前因为用到了“序列化”,所以可能会出现所谓的“内存碎片”的问题,详见下面链接:
而微软官方所推荐的方式如下(http://support.microsoft.com/kb/886385/en-us):
1. Create one instance of the XmlSerializer class, and put that instance in the cache by using
the caching APIs. For example, for a .dll file that is named HighSchool, the following code
caches one instance of the XmlSerializer class:
2 extraTypes, root, "http://www.microsoft.com");
3 Cache["HighSchoolSerializer"] = mySerializer
2. Use the instance of the XmlSerializer class that you put in the cache instead of creating a
new XmlSerializer object every time.
Use the following XmlSerializer class constructors. These class constructors cache the
assemblies:
In the .NET Framework version 1.0
public XmlSerializer(Type);2

In the .NET Framework version 1.1
2 public XmlSerializer(Type type, string defaultNamespace);
3
3. Declare the XmlSerializer object to be a static member of a class.
(这种方式是我们项目中所采用的方案)
如果大家对这个话题感兴趣,恰恰园子里就有朋友做这方面的探索,链接如下:
http://www.cnblogs.com/lixiong/archive/2007/10/26/938430.html
好了,今天的内容到此就要结束了。希望大家能够支持和关注我们这个本土开源项目。祝大家工作顺利,
生活幸福,谢谢大家:)
关键字:discuz,discuzNT,discuz.config,config,XmlSerializer,序列化,配置类,代震军,daizhj



浙公网安备 33010602011771号