zoukankan      html  css  js  c++  java
  • 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

      

  • 相关阅读:
    .NET面试题系列[2]
    .NET面试题系列[1]
    被淡忘的c#析构函数
    关于Spring IOC容器解释
    工作随笔记 点击除div自身之外的地方,关闭自己
    js获得控件位置
    PHP如何判断对象为空的方法分享
    PHP 网页调用本地exe程序实例
    PHP jQuery实现上传图片时预览图片的功能实例
    Yii 自带的分页实例
  • 原文地址:https://www.cnblogs.com/daizhj/p/989747.html
Copyright © 2011-2022 走看看