• 如何分离web.config改进版本


          三年前我分享了如何分离web.config中的配置节,因为有些项目过大,造成N多配置节存在于web.config中,缺点如下:
          1:不容易管理,当你想查找一个配置节时,望着整页的code,不知所措,为此你只有ctrl+f来解决。
          2:部署时也及容易出错,部署人员需要按照你写的部署文档,一个一个加,即费时又容易出错,比如一不小心将其它节点给覆盖了诸如此类。
          3:在web.config中的配置节的修改会引起站点重启。
          4:访问配置节不够简单,容易出错。

          文章之前我提到过我们为了解决此种问题的解决方案,就是将配置节从web.config文件中分离出来,将配置节存入单独的文件中。具体的方案请参考前面的文章(如何分割web.config ),有很长一段时间没有使用了,最近在使用上发现在多项目中复用有一定问题,即每个项目都需要编写一段不短的代码,下面就是我对于它的优化过程,先看下原来的工作量:

          第一:Webconfig,这是框架里面的内容,这也是唯一得以复用的地方。它是一个入口,所有的配置文件引用都通过它,比如访问酒店的配置类,WebConfig.Hotel.HotelName。代码如下:    

    View Code
    public partial  class WebConfig
        {
            /// <summary>
            
    /// 启动配置类
            
    /// </summary>
           public static void OnStart(string configFilePath, FileUpdate fileUpdate)
            {
                #region  实现配置文件独立
                //第一次启动需要执行委托方法更新配置类
                fileUpdate(configFilePath);
                //启动文件监视
                Log4netFileWatchHelper.StartWatching(fileUpdate, configFilePath);
                #endregion
            }
            /// <summary>
            
    /// Config/Web 文件夹的磁盘路径
            
    /// </summary>
           public static string ConfigFilePathRoot
           {
               get;
               set;
           }       
        }


           1:包含一个重要方法OnStart,可以对配置文件进行初始化,其实这个初始化也可以省略掉,因为完全可以将初始化配置类变成延迟加载模式。
           2:一个配置文件路径的属性,它标识了此项目类所有配置文件的存放目录,可以在程序初始化时指定此属性。

         第二:自定义的配置文件类,比如我们可以添加一个数据访问的配置类。

    View Code
     [Serializable ]
        public  class DataAccessConfig
        {   
            #region 需要序列化的配置文件属性
            /// <summary>
            
    /// 数据库信息列表
            
    /// </summary>
            public List<DataBase> DataBaseList { getset; }
            #endregion

            #region 相对于Config文件夹的子文件路径,不需要序列化.
            /// <summary>
            
    /// 相对于Config文件夹的子文件路径,不需要序列化.
            
    /// </summary>
            [NonSerialized()]
            private static string m_SubFilePath = @"DataAccessConfig.config";
            /// <summary>
            
    /// 子文件路径(排除config文件夹路径后的部分)
            
    /// </summary>
            public static string SubFilePath
            {
                get { return m_SubFilePath; }
                set { m_SubFilePath = value; }
            }
            #endregion
            public static DataAccessConfig CreateInstance()
            {
                FileUpdate fileUpdate = new FileUpdate(WebConfig.DataAccessConfigOnUpdate);
                string configFilePath = WebConfig.ConfigFilePathRoot + DataAccessConfig.SubFilePath;
                if (!File.Exists(configFilePath))
                {
                    return null;
                }
                DataAccessConfig config = SerializationHelper.Load(typeof(DataAccessConfig), configFilePath) as DataAccessConfig;
                //启动文件监视
                Log4netFileWatchHelper.StartWatching(fileUpdate, configFilePath);
                return config;
            }     
        }
       
        public partial class WebConfig
        {
            #region 第二步:为DataAccessConfig类添加入口
            /// <summary>
            
    /// 属性对应的私有变量
            
    /// </summary>
            private static DataAccessConfig m_DataAccessConfig = null;
            /// <summary>
            
    /// 属性访问器.通过WebConfig.SimpleFileDemoConfig可以访问此类.
            
    /// </summary>
            public static DataAccessConfig DataAccessConfig
            {
                get
                {
                    if (m_DataAccessConfig == null)
                        Interlocked.CompareExchange<DataAccessConfig>(ref m_DataAccessConfig,
                            DataAccessConfig.CreateInstance(), null);
                    return m_DataAccessConfig;
                }
            }
            #endregion

            #region 第三步:为DataAccessConfig类添加更新函数
            /// <summary>
            
    /// 更新函数
            
    /// </summary>
            
    /// <param name="status"></param>
            public static void DataAccessConfigOnUpdate(object status)
            {
                lock (WebConfig.DataAccessConfig)
                {
                    try
                    {
                        m_DataAccessConfig = DataAccessConfig.CreateInstance();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }
            #endregion
        }

           这段代码就是我们要实现的部分,不能复用,总觉的需要改进一下,问题分析:
           1:由于需要采用静态调用方式,为此要想通过WebConfig的静态属性调用,就需要在WebConfig类中增加自定义配置类的属性,比如我们增加一个Hotel相关的配置类,而要想WebConfig.Hotel,就需要增加一个静态属性方式实现。这里可以稍微修改下,即最后在配置自定义配置类时只编写自定义配置类,而不用去编写WebConfig类。
           2:自定义配置类中的CreateInstance,也要考虑复用。

           原则就是自定义的配置类不关心如何读取配置文件,只关心自己的配置属性即可。
           
           改善后的版本:
           1:针对WebConfig.自定义类方式。这里我修改的方法也不是最好的,用起来没有修改前的顺畅,但代码确实精简了。思路就是在WebConfig类中生成一个泛型配置类。
           

    public partial class WebConfig<T> :WebConfig where T:class

           这里新增了WebConfig的泛型版本,而将WebConfig提取成基类,WebConfig类中包含一个属性,即配置文件所在文件夹路径。
          

     /// <summary>
            
    /// Config/Web 文件夹的磁盘路径
            
    /// </summary>
            public static string ConfigFilePathRoot
            {
                get;
                set;
            }

            WebConfig<T>主要目的是为了生成T类型的配置类,这里将原本在自定义配置类中的代码提取到WebConfig<T>中:

    View Code
             /// <summary>
            
    /// 属性对应的私有变量
            
    /// </summary>
            private static T m_DataAccessConfig ;
            /// <summary>
            
    /// 属性访问器.通过WebConfig.SimpleFileDemoConfig可以访问此类.
            
    /// </summary>
            public static T DataAccessConfig
            {
                get
                {
                    if (m_DataAccessConfig == null)
                        Interlocked.CompareExchange<T>(ref m_DataAccessConfig,
                            CreateInstance(), null );
                    return m_DataAccessConfig;
                }
            }        
             /// <summary>
            
    /// 更新函数
            
    /// </summary>
            
    /// <param name="status"></param>
            public static void DataAccessConfigOnUpdate(object status)
            {
                lock (WebConfig<T>.DataAccessConfig)
                {
                    try
                    {
                        m_DataAccessConfig = CreateInstance();
                    }
                    catch (Exception ex)
                    {
                        throw ex;
                    }
                }
            }

        
            2:将自定义配置类生成实例的方法也进行封装。
             

    private static T CreateInstance()
            {
                SubFilePath = typeof(T).Name+".config";
                string configFilePath = WebConfig<T>.ConfigFilePathRoot + SubFilePath;
                if (!File.Exists(configFilePath))
                {
                    return null;
                }
                T config = SerializationHelper.Load(typeof(T), configFilePath) as T;
                //启动文件监视
                FileWatch(configFilePath);
                return config;            

            }

            
            有了上面的提取封装,下面就是改版后的自定义类了,到目前为止,我们编写一个自定义配置类的成本已经非常低了:
            

    [Serializable]
        public class MyConfig : WebConfig<DataAccessConfig>
        {
            #region 需要序列化的配置文件属性
            public string ExpenseTemplateFile { getset; }
            public bool Switch { getset; }
            #endregion      
        }

           最后我们添加一个配置文件,名称和自定义配置类保持一致。
          

      <?xml version="1.0" encoding="utf-8" ?>
    <MyConfig>
      <ExpenseTemplateFile>ssssss3</ExpenseTemplateFile>
      <Switch>false</Switch>
    </MyConfig>

        
          客户端调用方式:   

    WebConfig<MyConfig>.DataAccessConfig.Switch

          

           虽然本次改版并不完美,但在多个项目中利用时还是起到了很大的作用,编写简单,调用方便,唯一不满意的就是需要这样写:WebConfig<MyConfig>,没有以前的WebConfig.MyConfig方式来的舒服。

  • 相关阅读:
    Python 的 Pandas 对矩阵的行进行求和
    python 统计字符串中指定字符出现次数的方法
    Python 2 代码转 Python 3的一些转化
    Python 的文件保存路径
    Pycharm 个人认为舒服漂亮又好用的主题风格
    【RS】Collaborative Memory Network for Recommendation Systems
    MATLAB 条形图添加多个图例
    MATLAB 画柱状图(/直方图)修改横坐标名称并使其横着显示
    Nexus3.X 将Maven项目上传至nexus私服
    nexus maven 使用案例
  • 原文地址:https://www.cnblogs.com/ASPNET2008/p/2322039.html
Copyright © 2020-2023  润新知