一个比较通用简单易用的配置功能

   以前写过两篇关于如何分离web.config的文章(如何分割web.config,  如何分离web.config改进版本, ),至于为什么要分离,我当时的观点如下:
   
   因为有些项目过大,造成N多配置节存在于web.config中,缺点如下:
      1:不容易管理,当你想查找一个配置节时,望着整页的code,不知所措,为此你只有ctrl+f来解决。
      2:部署时也及容易出错,部署人员需要按照你写的部署文档,一个一个加,即费时又容易出错,比如一不小心将其它节点给覆盖了诸如此类。
      3:在web.config中的配置节的修改会引起站点重启。
      4:访问配置节不够简单,容易出错。
      
   朋友春天在哪里看了文章后,提到:web.config就已经支持分离配置文件了(configSource attribute),同时transform web.config也支持不同configuration。当时没太在意,正好,最近项目中再次应用到配置文件组件,就顺便看了下configSource attribute。
   
   configSource attribute能够很好的分离多配置节点,至于修改分离后的配置文件是否会引启站点重启,我并未了解,未做仔细研究。
   
   这篇主要对比下我的自定义配置文件组件的优势以及它的适用场景。
   
   适用场景:
  

   1:非环境相关的内容。
      这里先解释下什么是环境相关以及非环境相关。
      环境相关:上线时需要修改的内容,比如数据库连接串,邮箱服务器信息等等。
      非环境相关:上线时不需要修改的内容,即和业务逻辑相关的一些配置,开发环境和生产环境值并不一定需要不同。
      
      我不太主张将环境相关的内容也转移到自定义的配置文件中,比如数据连接串,web.config对数据库连接串会有更好的加密机制,我们就没有必要多费劳力去做微软已经提供的功能。
      
   2: 适用于配置项内容为记录集形式。
      这里拿我最近的一个项目来分享。
      需求:网站有一个发布静态文本的功能,比如用户选择首页,然后在富文本编辑器中加载对应页面默认的文本内容。方便发布,有些页面只需要随便修改点内容就可以。
      分析:需要支持多页面,需要支持多语言。这样的默认文本配置项比较符合记录集的概念。
      这种需求,很明显我们不能放在Web.Config文件中。
      首次是web.config中不适合存放富文本内容,一般情况下,只存放简单类型的值,其次,在web.config中要想实现上面的需求会更加复杂,先不说多节点的配置,就是程序中读取对应语言对应页面的内容,免不了一堆的条件判断。
      
      下面是我定义的配置文件:
      可以非常好的支持多语言,以及多页面。

<?xml version="1.0" encoding="utf-8" ?>
<StaticPageContentConfig>
  <LanguageItems>
    <LanguageItem>
      <Name>zh-CHS</Name>
      <Pages>
        <Page>
          <Name>Home</Name>
          <Content>
            <![CDATA[
            这里是首页html
    ]]>
          </Content>
        </Page>
        <Page>
          <Name>Awards</Name>
          <Content>
<![CDATA[
      这里是奖金html
    ]]>
          </Content>
        </Page>       
      </Pages>
    </LanguageItem>
  </LanguageItems>
</StaticPageContentConfig>


    我们在看下,程序如果根据语言以及页面获取对应的html信息。纯属集合操作。
   

var StaticContentHtml = WebConfig<StaticPageContentConfig>.DataAccessConfig.LanguageItems.Where(
               P => P.Name == "语言参数").FirstOrDefault();
            if (null != StaticContentHtml)
            {
                var page = StaticContentHtml.Pages.Where(p => p.Name == "页面参数").FirstOrDefault();
                if (null != page)
                {
                    result = page.Content;
                }
            }

            

      上篇文章我曾经对配置节点的访问有点有遗憾,WebConfig<StaticPageContentConfig>.DataAccessConfig.LanguageItems这种方式不是特别简单,我认为比较合理的方式:StaticPageContentConfig.LanguageItems。这次想了个比较简单的办法,主要是在实体类的定义中做一个变量(static StaticPageContentConfig Data):
   

[Serializable]
    public class StaticPageContentConfig
    {
        public List<LanguageItem> LanguageItems { getset; }
         public static StaticPageContentConfig Data
        {
            get
            {
                return WebConfig<StaticPageContentConfig>.DataAccessConfig;
            }
           
        }
        
    }
    [Serializable]
    public class Page
    {
        public string Name { getset; }
        public string Content { getset; }

    }
    [Serializable]
    public class LanguageItem
    {
        public string Name { getset; }
        public List<Page> Pages { getset; }
 
    }

    
    最后可以这样访问:var StaticContentHtml = StaticPageContentConfig.Data.LanguageItems
    
    自定义配置组件优势:
    1:可以支持一些不适用放在web.config中的节点,比如富文本之类。
    2:很好的支持集合类型的配置。
    3:读取数据时,不再需要传入节点名称的字符串,取而代之是纯类对象属性操作,基本不会因为参数传递错误,导致程序出现BUG。

       web.config方式  :

  public static string GetAppSetting(string keyWord)
        {
            var result = string.Empty;
            if (ConfigurationManager.AppSettings[keyWord] != null)
                result = ConfigurationManager.AppSettings[keyWord].Trim();
            return result;
        }


      组件方式:StaticPageContentConfig.Data.LanguageItems,不需要传递节点名称。

    总之:

         可以很好的结合web.config本身的优势以及自定义配置组件的优点,来打造一个比较通用简单易用的配置功能。

posted on 2012-06-09 11:29  min.jiang  阅读(3283)  评论(0编辑  收藏  举报