如果大家从官方下载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的定义如下:
2 /// 文件配置管理基类
3 /// </summary>
4 public class DefaultConfigFileManager
5 {
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 ConfigFilePath
26 {
27 get { return m_configfilepath; }
28 set { m_configfilepath = value; }
29 }
30
31
32 /// <summary>
33 /// 临时配置对象
34 /// </summary>
35 public static IConfigInfo ConfigInfo
36 {
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 else
82 {
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 try
107 {
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 finally
117 {
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 try
144 {
145 fs = new FileStream(configFilePath, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
146 XmlSerializer serializer = new XmlSerializer(configinfo.GetType());
147 serializer.Serialize(fs, configinfo);
148 //成功则将会返回true
149 succeed = true;
150 }
151 catch (Exception ex)
152 {
153 throw ex;
154 }
155 finally
156 {
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
2 /// Discuz!NT 配置管理类接口
3 /// </summary>
4 public interface IConfigFileManager
5 {
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
2 /// Discuz!NT 配置信息类接口
3 /// </summary>
4 public interface IConfigInfo
5 {
6 }
7
大家可以看到,其中的 IConfigInfo接口没有任何属性和方法,是一个“空接口”,这主要是为
了提供统一的向上转型需要。当然,如果以后有需要还是会添加一些方法和属性的。
为了减少篇幅,下面只对其中的 GeneralConfig进行相应介绍,一是因为它是核心的配置类,有
关它的使用在项目中不胜枚举。另外它也是这个项目中比较标准的“宝贝”,从一开始,只要有新的
功能往往都会对这个配置类有所“关照”。下面就是通过反射后得到的代码,相关的说明见注释即可:
论坛全局配置管理类(GeneralConfigFileManager):
2 /// 全局配置设置管理类
3 /// </summary>
4 class GeneralConfigFileManager : Discuz.Config.DefaultConfigFileManager
5 {
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 try
23 {
24 m_configinfo = (GeneralConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(GeneralConfigInfo));
25 }
26 catch
27 {
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 ConfigInfo
37 {
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 ConfigFilePath
52 {
53 get
54 {
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 try
73 {
74 ConfigInfo = DefaultConfigFileManager.LoadConfig(ref m_fileoldchange, ConfigFilePath, ConfigInfo, true);
75 }
76 catch
77 {
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):
2 /// 论坛全局配置类
3 /// </summary>
4 public class GeneralConfigs
5 {
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 /// 获取默认模板id
48 /// </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 try
68 {
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 catch
75 {
76 return false;
77 }
78
79 }
80 return result;
81
82 }
83
84
85 Helper
108 }
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
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