zoukankan      html  css  js  c++  java
  • Discuz!NT 慢慢分析之开篇Config 的实现

    其实很早的时候就想琢磨下Discuz!NT的一些东西,今天着重吧Discuz 的有关于配置的信息研究了下,拿出来与大家共同分享下

    Discuz!NT在web.config自定义了httpModule 模块去实现了IHttpModule

    <httpModules>
        <add type="Discuz.Forum.HttpModule, Discuz.Forum" name="HttpModule" />
    </httpModules>
    这样的话,在程序启动的时候,则首先执行此处的HttpModule里的Init方法
     public void Init(HttpApplication context)
     {
         OnlineUsers.ResetOnlineList();
         context.BeginRequest += new EventHandler(ReUrl_BeginRequest);
         if (eventTimer == null && ScheduleConfigs.GetConfig().Enabled)
         {

    EventLogs.LogFileName = Utils.GetMapPath(string.Format("{0}cache/scheduleeventfaildlog.config",

    BaseConfigs.GetForumPath));

             EventManager.RootPath = Utils.GetMapPath(BaseConfigs.GetForumPath);

    eventTimer = new Timer(new TimerCallback(ScheduledEventWorkCallback), context.Context,

    60000, EventManager.TimerMinutesInterval * 60000);

         }
         context.Error += new EventHandler(Application_OnError);
     }

    一行一行的讲解:

    OnlineUsers.ResetOnLineList首先将用户信息清零

    context.BeginRequest += new EventHandler(ReUrl_BeginRequest) 这行代码指定地址请求处理的方法(ReUrl_BeginRequest这个方法是处理URL 地址的)

    if(eventTimer == null && ScheduleConfigs.GetConfig().Enabled) 判断是否配置开启了“计划任务”且计时器是否初始化

    如果开启了“计划任务”且计时器未启动,则启用计划任务信息

    最后context.Error += new EventHandler(Application_OnError) 为异常处理

    这是上面的是大方向,今天就说一个地方:ScheduleConfigs.GetConfig()这句话,

    也就是Discuz!NT 采用的配置文件方式

    Discuz!NT 将配置文件大部分的放入了web底下的config 目录里了,当然还有个最主要的DNT.Config放在外面

    image

    里面的结构大致如下所示

    image

    介绍下各个类的作用     

    ScheduleConfigs 是对外部公开的对象,它仅有两个功能,一是读出配置文件,二是存储配置文件信息,均无参数/

    ScheduleConfigInfo 是一个领域模型,对应相应配置的config,为了统一方便处理,这里实现了仅作规定约束的IConfigInfo接口,此接口没有任何内容。

    实现ScheduleConfigs 中的功能主要依赖于

    ScheduleConfigFileManager,其中用static 存储配置信息,由于是static型的,则只需要存储一次即可供全局共享

    大概就是这样,后来我把Discuz!NT 的配置单独抽出来了,大概是这样的样子的

    image

    在这里我只向外部暴露DeclareDatertimeConfigs   这个类,其余的都为internal

    部分代码如下

        public class DeclareDateTimeConfigs
        {
     
            /// <summary>
            /// 获取配置类实例
            /// </summary>
            /// <returns></returns>
            public static DeclareDateTimeConfigInfo GetConfig()
            {
                return DeclareDateTimeConfigFileManager.LoadConfig();
            }
     
            /// <summary>
            /// 保存配置类实例
            /// </summary>
            /// <returns></returns>
            public static bool SaveConfig(DeclareDateTimeConfigInfo declareDateTimeConfigInfo)
            {
                DeclareDateTimeConfigFileManager scfm = new DeclareDateTimeConfigFileManager();
                DeclareDateTimeConfigFileManager.ConfigInfo = declareDateTimeConfigInfo;
                return scfm.SaveConfig();
            }
     
     
        }
        internal class DeclareDateTimeConfigFileManager:DefaultConfigFileManager
        {
            private static DeclareDateTimeConfigInfo m_configinfo;
     
            /// <summary>
            /// 锁对象
            /// </summary>
            private static object m_lockHelper = new object();
     
            /// <summary>
            /// 文件修改时间
            /// </summary>
            private static DateTime m_fileoldchange;
     
            /// <summary>
            /// 初始化文件修改时间和对象实例
            /// </summary>
            static DeclareDateTimeConfigFileManager() {
                m_fileoldchange = System.IO.File.GetLastWriteTime(ConfigFilePath);
                m_configinfo = (DeclareDateTimeConfigInfo)DefaultConfigFileManager.DeserializeInfo(ConfigFilePath, typeof(DeclareDateTimeConfigInfo));
     
            }
            public new static IConfigInfo ConfigInfo
            {
                get { return m_configinfo; }
                set { m_configinfo = (DeclareDateTimeConfigInfo)value; }
            }
     
            /// <summary>
            /// 配置文件所在路径
            /// </summary>
            public static string filename = null;
     
     
            /// <summary>
            /// 获取配置文件所在路径
            /// </summary>
            public new static string ConfigFilePath
            {
                get
                {
                    if (filename == null)
                    {
                        {
                            filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Config\\DeclareDateTime.config");
                        }
     
                        if (!File.Exists(filename))
                        {
                            throw new Exception("发生错误: 虚拟目录或网站根目录下没有正确的DNT.config文件");
                        }
                    }
                    return filename;
                }
     
            }
     
            /// <summary>
            /// 加载配置类
            /// </summary>
            /// <returns></returns>
            public static DeclareDateTimeConfigInfo LoadConfig()
            {
                ConfigInfo = DefaultConfigFileManager.LoadConfig(ref m_fileoldchange, ConfigFilePath, ConfigInfo);
                return ConfigInfo as DeclareDateTimeConfigInfo;
            }
     
            /// <summary>
            /// 加载真正有效的配置类
            /// </summary>
            /// <returns></returns>
            public static DeclareDateTimeConfigInfo LoadRealConfig()
            {
                ConfigInfo = DefaultConfigFileManager.LoadConfig(ref m_fileoldchange, ConfigFilePath, ConfigInfo, false);
                return ConfigInfo as DeclareDateTimeConfigInfo;
            }
     
            /// <summary>
            /// 保存配置
            /// </summary>
            /// <returns></returns>
            public override bool SaveConfig()
            {
                return base.SaveConfig(ConfigFilePath, ConfigInfo);
            }
        }
        internal class DefaultConfigFileManager
        {
            /// <summary>
            /// 文件所在路径变量
            /// </summary>
            private static string m_configfilepath;
     
            /// <summary>
            /// 临时配置对象变量
            /// </summary>
            private static IConfigInfo m_configinfo = null;
     
            /// <summary>
            /// 锁对象
            /// </summary>
            private static object m_lockHelper = new object();
     
     
            /// <summary>
            /// 文件所在路径
            /// </summary>
            public static string ConfigFilePath
            {
                get { return m_configfilepath; }
                set { m_configfilepath = value; }
            }
     
     
            /// <summary>
            /// 临时配置对象
            /// </summary>
            public static IConfigInfo ConfigInfo
            {
                get { return m_configinfo; }
                set { m_configinfo = value; }
            }
     
            /// <summary>
            /// 加载(反序列化)指定对象类型的配置对象
            /// </summary>
            /// <param name="fileoldchange">文件加载时间</param>
            /// <param name="configFilePath">配置文件所在路径</param>
            /// <param name="configinfo">相应的变量 注:该参数主要用于设置m_configinfo变量 和 获取类型.GetType()</param>
            /// <returns></returns>
            protected static IConfigInfo LoadConfig(ref DateTime fileoldchange, string configFilePath, IConfigInfo configinfo)
            {
                return LoadConfig(ref fileoldchange, configFilePath, configinfo, true);
            }
     
     
            /// <summary>
            /// 加载(反序列化)指定对象类型的配置对象
            /// </summary>
            /// <param name="fileoldchange">文件加载时间</param>
            /// <param name="configFilePath">配置文件所在路径(包括文件名)</param>
            /// <param name="configinfo">相应的变量 注:该参数主要用于设置m_configinfo变量 和 获取类型.GetType()</param>
            /// <param name="checkTime">是否检查并更新传递进来的"文件加载时间"变量</param>
            /// <returns></returns>
            protected static IConfigInfo LoadConfig(ref DateTime fileoldchange, string configFilePath, IConfigInfo configinfo, bool checkTime)
            {
                lock (m_lockHelper)
                {
                    m_configfilepath = configFilePath;
                    m_configinfo = configinfo;
     
                    if (checkTime)
                    {
                        DateTime m_filenewchange = System.IO.File.GetLastWriteTime(configFilePath);
     
                        //当程序运行中config文件发生变化时则对config重新赋值
                        if (fileoldchange != m_filenewchange)
                        {
                            fileoldchange = m_filenewchange;
                            m_configinfo = DeserializeInfo(configFilePath, configinfo.GetType());
                        }
                    }
                    else
                        m_configinfo = DeserializeInfo(configFilePath, configinfo.GetType());
     
                    return m_configinfo;
                }
            }
     
     
            /// <summary>
            /// 反序列化指定的类
            /// </summary>
            /// <param name="configfilepath">config 文件的路径</param>
            /// <param name="configtype">相应的类型</param>
            /// <returns></returns>
            public static IConfigInfo DeserializeInfo(string configfilepath, Type configtype)
            {
                return (IConfigInfo)SerializationHelper.Load(configtype, configfilepath);
            }
     
            /// <summary>
            /// 保存配置实例(虚方法需继承)
            /// </summary>
            /// <returns></returns>
            public virtual bool SaveConfig()
            {
                return true;
            }
     
            /// <summary>
            /// 保存(序列化)指定路径下的配置文件
            /// </summary>
            /// <param name="configFilePath">指定的配置文件所在的路径(包括文件名)</param>
            /// <param name="configinfo">被保存(序列化)的对象</param>
            /// <returns></returns>
            public bool SaveConfig(string configFilePath, IConfigInfo configinfo)
            {
                return SerializationHelper.Save(configinfo, configFilePath);
            }
        }
        internal class SerializationHelper
        {
            private SerializationHelper()
            { }
     
            private static Dictionary<int, XmlSerializer> serializer_dict = new Dictionary<int, XmlSerializer>();
     
            public static XmlSerializer GetSerializer(Type t)
            {
                int type_hash = t.GetHashCode();
     
                if (!serializer_dict.ContainsKey(type_hash))
                    serializer_dict.Add(type_hash, new XmlSerializer(t));
     
                return serializer_dict[type_hash];
            }
     
     
            /// <summary>
            /// 反序列化
            /// </summary>
            /// <param name="type">对象类型</param>
            /// <param name="filename">文件路径</param>
            /// <returns></returns>
            public static object Load(Type type, string filename)
            {
                FileStream fs = null;
                try
                {
                    // open the stream...
                    fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
                    XmlSerializer serializer = new XmlSerializer(type);
                    return serializer.Deserialize(fs);
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (fs != null)
                        fs.Close();
                }
            }
     
     
            /// <summary>
            /// 序列化
            /// </summary>
            /// <param name="obj">对象</param>
            /// <param name="filename">文件路径</param>
            public static bool Save(object obj, string filename)
            {
                bool success = false;
     
                FileStream fs = null;
                // serialize it...
                try
                {
                    fs = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.ReadWrite);
                    XmlSerializer serializer = new XmlSerializer(obj.GetType());
                    serializer.Serialize(fs, obj);
                    success = true;
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (fs != null)
                        fs.Close();
                }
                return success;
     
            }
     
            /// <summary>
            /// xml序列化成字符串
            /// </summary>
            /// <param name="obj">对象</param>
            /// <returns>xml字符串</returns>
            public static string Serialize(object obj)
            {
                string returnStr = "";
                XmlSerializer serializer = GetSerializer(obj.GetType());
                MemoryStream ms = new MemoryStream();
                XmlTextWriter xtw = null;
                StreamReader sr = null;
                try
                {
                    xtw = new System.Xml.XmlTextWriter(ms, Encoding.UTF8);
                    xtw.Formatting = System.Xml.Formatting.Indented;
                    serializer.Serialize(xtw, obj);
                    ms.Seek(0, SeekOrigin.Begin);
                    sr = new StreamReader(ms);
                    returnStr = sr.ReadToEnd();
                }
                catch (Exception ex)
                {
                    throw ex;
                }
                finally
                {
                    if (xtw != null)
                        xtw.Close();
                    if (sr != null)
                        sr.Close();
                    ms.Close();
                }
                return returnStr;
     
            }
     
            public static object DeSerialize(Type type, string s)
            {
                byte[] b = System.Text.Encoding.UTF8.GetBytes(s);
                try
                {
                    XmlSerializer serializer = GetSerializer(type);
                    return serializer.Deserialize(new MemoryStream(b));
                }
                catch (Exception ex)
                {
                    throw ex;
                }
            }
        }

    使用时候非常方便,使用下列语句

                var config = DeclareDateTimeConfigs.GetConfig();

    即可得到配置信息

    存储配置信息也很简单  

                DeclareDateTimeConfigs.SaveConfig(config);

       因为此处是static   所以可以不用考虑缓存的问题

  • 相关阅读:
    有道翻译js解密(1)
    Python面试题之Python正则表达式re模块
    go语言从例子开始之Example4.常量
    go语言从例子开始之Example3.变量
    go语言从例子开始之Example2.类型
    go语言从例子开始之Example1.helloworld
    python模块打补丁
    gevent协程之猴子补丁带来的坑
    charles抓包小程序
    httptesting HTTP(s)接口自动化测试框架
  • 原文地址:https://www.cnblogs.com/jicheng1014/p/1933402.html
Copyright © 2011-2022 走看看