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.csEmai-
lConfigFileManager.cs
BaseConfigFileManager.csAlbumConfigFileManager.csAggregatio-
nConfigFileManager.cs
, SpaceActiveConfigFileManager.cs分别派生自DefaultConfigFileManager。
而DefaultConfigFileManager本身也定义了几个属性和方法以便于子类调用或重写(如SaveConfig)。
而DefaultConfigFileManager的定义如下:

   

  1 /// <summary>
  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

    

 1/// <summary>
 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

   

1 /// <summary>
2    /// Discuz!NT 配置信息类接口
3    /// </summary>

4    public interface IConfigInfo
5    {
6    }

7

    大家可以看到,其中的 IConfigInfo接口没有任何属性和方法,是一个“空接口”,这主要是为
了提供统一的向上转型需要。当然,如果以后有需要还是会添加一些方法和属性的。
 
    为了减少篇幅,下面只对其中的 GeneralConfig进行相应介绍,一是因为它是核心的配置类,有
关它的使用在项目中不胜枚举。另外它也是这个项目中比较标准的“宝贝”,从一开始,只要有新的
功能往往都会对这个配置类有所“关照”。下面就是通过反射后得到的代码,相关的说明见注释即可:


    论坛全局配置管理类(GeneralConfigFileManager):

    

 1/// <summary>
 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):

 

Code


 论坛全局配置类(GeneralConfigs):

 

  1 /// <summary>
  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
:

 

1  XmlSerializer mySerializer = new XmlSerializer(typeof(HighSchool.MyClass), attrOverrides, 
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
       

1public XmlSerializer(Type);
2

       In the .NET Framework version 1.1
      

1  public XmlSerializer(Type type);
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

  

posted @ 2007-12-10 18:55  代震军  阅读(12507)  评论(59编辑  收藏