• Web.config自定义节点configSections


     

    由于最近一个项目的数据库变动比较频繁, 为了减少数据层的负担, 打算采用.net的MVC框架, 使用LINQ对付数据层.

     
        这个框架的web.config文件里出现了configSections section, 这个之前没有留意, 乘着项目不是很急, 顺势把它给搞懂, 花了一下午时间, 终于搞定, 有点心得, 写下来以供面试官翻阅.
     
        asp.net为啥要引用configSections?
    因为用户的一些对象, 可能在config里进行配置, 但是config怎么能随便让你添加自己的节点呢! 不行你自己试试, 在任何位置添加任何没有申明的节点, 系统都不会让你通过, 更不会让你去读它了, 当然, 你打算在别的xml文件里添加节点, 然后读出来, 创建对象, 这个没问题.
     
    为了系统能有组织的管理用户的在配置文件里的自定义信息, 就要使用configSections了, 分3步走:
      1. 创建一个实现IConfigurationSectionHandler的类 
     
      2. 在config文件里添加如下节点:
     
      <configuration>
                  <configSections>
                       <section name="NameM" type="LearningConfiguration.NameSectionHandler"/>
                  </configSections>
                  <NameM>
                       <Add key="name1" firstname="Jim" lastname="w1"/>
                       <Add key="name2" firstname="Chris" lastname="w2"/>
                   </NameM>
        
            说明: 在configSections下添加一个section子节点, 写好标示名和类型, 然后在紧接这下面实现这个标示名的细节内容,就是我们当初想添加的自己的自定义信息了.
           
        3. 实现IConfigurationSectionHandler唯一的方法: public object Create(object parent, object configContext, XmlNode section), 这里的最后一个参数就是自定义信息那个节点了, 粗体部分. 通过处理这堆信息, 返回你要的对象.
     
           4. 使用这个返回的对象,通过System.Configuration.ConfigurationManager.GetSection()方法.
     
    以下是示例代码:
    (NameSectionHandler.cs)

    namespace LearningConfiguration
    {
        
    public class NameSectionHandler : IConfigurationSectionHandler
        {
            
    #region IConfigurationSectionHandler Members
            
    public object Create(object parent, object configContext, XmlNode section)
            {
                Dictionary
    <string, NameManagement> names = new Dictionary<string, NameManagement>();
                
                
    string key = string.Empty;
                
    string firstName = string.Empty;
                
    string lastName = string.Empty;
                
    foreach (XmlNode childNode in section.ChildNodes)
                {
                    
    if (childNode.Attributes["key"!= null)
                    {
                        key 
    = childNode.Attributes["key"].Value;

                        
    if (childNode.Attributes["firstname"!= null)
                        {
                            firstName 
    = childNode.Attributes["firstname"].Value;
                        }
                        
    else
                        {
                            firstName 
    = string.Empty;
                        }
                        
    if (childNode.Attributes["lastname"!= null)
                        {
                            lastName 
    = childNode.Attributes["lastname"].Value;
                        }
                        
    else
                        {
                            lastName 
    = string.Empty;
                        }
                        names.Add(key, 
    new NameManagement(firstName, lastName));
                    }
                }
                
    return names;
            }
            
    #endregion
        }
    }
    (NameManagement.cs)
    复制代码
    namespace LearningConfiguration
    {
        
    public class NameManagement
        {
            
    string _firstName;
            
    public string FirstName
            {
                
    get { return this._firstName; }
                
    set { this._firstName = value; }
            }
            
    string _lastName;
            
    public string LastName
            {
                
    get { return this._lastName; }
                
    set { this._lastName = value; }
            }
            
    public NameManagement(string firstName, string lastName)
            {
                
    this.FirstName = firstName;
                
    this.LastName = lastName;
            }
            
    public string RetrieveFullName()
            {
                
    return string.Format("{0} {1}"this.FirstName, this.LastName);
            }
        }
    }
    复制代码
    (Default.aspx.cs)
    复制代码
    namespace LearningConfiguration
    {
        
    public partial class _Default : System.Web.UI.Page
        {
            
    protected void Page_Load(object sender, EventArgs e)
            {
                Dictionary
    <string, NameManagement> names = ConfigurationManager.GetSection("NameM"as Dictionary<string, NameManagement>;
                
    if (names != null)
                { 
                    
    foreach(string key in names.Keys)
                    {
                        NameManagement name 
    = names[key] as NameManagement;
                        Response.Write(name.RetrieveFullName());
                    }
                }
            }
        }
    }
    复制代码
     与以上调用方式一样:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.UI;
    using System.Web.UI.WebControls;
    using System.Configuration;
    using System.Collections.Specialized;
    using LearningConfiguation;

    public partial class Default4 : System.Web.UI.Page
    {
        
    protected void Page_Load(object sender, EventArgs e)
        {
            Dictionary
    <String, NameManagement> names = System.Configuration.ConfigurationManager.GetSection("test/aa"as Dictionary<String, NameManagement>;
            Dictionary
    <String, NameManagement>.KeyCollection keys = names.Keys;
            
    foreach (String key in keys)
            {
                NameManagement nm 
    = names[key] as NameManagement;
                Response.Write(nm.FirstName);
                Response.Write(
    "<br>");
                Response.Write(nm.LastName);
            }
        }
    }

     

     

     

    1.为什么需要自定义节点

    为了增加应用程序的可移植性,通常网站需要配置一些自定义的节点,例如:文件上传的路径等,再深入的应用,可以定义工厂方法需要创建的类。

    2.configSections使用方法

    configSections节点下定义自定义节点可以帮我们实现我们自己的节点。

    首先定义自己的节点,定义方法如下:

    < configSections >
        
    < sectionGroup name = " section group name " >
            
    < section name = " section name "  type = " configuration section handler class "   />
        
    </ sectionGroup >
    </ configSections >

     定义自己的节点必须在 configSections 节点。

    sectionGroup  元素充当   section  元素的容器。

    section  元素将配置节处理程序与配置元素或节关联。由于   ASP.NET  不对如何处理配置文件内的设置作任何假设,因此这非常必要。但   ASP.NET  会将配置数据的处理委托给配置节处理程序, ( 稍候说明。 ) 每个   section  元素均标识一个配置节或元素。可以在   sectionGroup  元素中对   section  元素进行逻辑分组,以对   section  元素进行组织并避免命名冲突。 section    sectionGroup  元素包含在   configSections  元素中。

    sectionGroup 节点属性:

    name :必选的   String  属性, 这是   group   元素在配置文件的节设置区域中使用的名称。

    section 节点属性:

    name :必选的   String  属性,指定与   type  属性中指定的配置节处理程序关联的配置节或元素的名称。这是该元素在配置文件的节设置区域中使用的名称。

    type :必选的   String   属性,指定用来执行如下操作的配置节处理程序类的名称:处理在   name   属性中指定的节或元素中的配置设置。


    现在定义好了自己的节点,可以使用该节点了。使用方法如下:

    < section group name >
        
    < section name >
            
    < add key = " key1 "  value = " value1 "   />
        
    </ section name >
    </ section group name >  

     定义好了自己的节点,如何读取节点信息呢?

    以下是 msdn 上的原话:

    您可以用自己的   XML  配置元素来扩展标准的   ASP.NET  配置设置集。若要完成该操作,您必须创建自己的配置节处理程序。

    该处理程序必须是一个实现   System.Configuration.IConfigurationSectionHandler  接口或   System.Configuration.ConfigurationSection  类的   .NET Framework 类。

    节处理程序解释并处理   Web.config  文件特定部分中   XML  配置元素中定义的设置,并根据配置设置返回适当的配置对象。处理程序类返回的配置对象可以是任何数据结构;它不限于任何基配置类或配置格式。 ASP.NET  使用该配置对象,以对自定义配置元素进行读取和写入。

    上面这段话的意思就是说,我们要定义一个类,这个类要继承自 System.Configuration.IConfigurationSectionHandler  接口或 System.Configuration.ConfigurationSection  类。

    然后用这个类来处理我们自定义的节点。

    我们看到 System.Configuration.IConfigurationSectionHandler 接口中,只有一个方法 :

    // 创建配置节处理程序
    Object Create (Object parent, Object configContext, XmlNode section)

     

    返回值

    创建的节处理程序对象。


    这个类是干什么用的呢?让我们通过一个例子来看看。

     

    首先,我们新建一个网站项目,并在 web.config 中加入以下节点:

    < configSections >
        
    < sectionGroup name = " WebSiteInfo " >
            
    < section name = " basicInfo "  type = " ConfigurationSectionTest.WebSiteInfoHandler " />
            
    < section name = " fileUpload "  type = " ConfigurationSectionTest.WebSiteInfoHandler " />
        
    </ sectionGroup >
    </ configSections >

    < WebSiteInfo >
        
    < basicInfo >
            
    < add key = " name "  value = " huchen's homepage " />
            
    < add key = " version "  value = " 1.0 " />
        
    </ basicInfo >
        
    < fileUpload >
            
    < add key = " fileUploadPath "  value = " E://MyHomePage//Web//Upload// " />
            
    < add key = " fileUploadSizeMax "  value = " 2M " />
        
    </ fileUpload >
    </ WebSiteInfo >

     

    以上我们在 WebSiteInfo 节点下定义了两个节点 basicInfo fileUpload ,并定义了节点处理程序类 ConfigurationSectionTest.WebSiteInfoHandler ,并且随后运用了我们定义的节点。

    我们来看看节点处理程序 ConfigurationSectionTest.WebSiteInfoHandler。

    任意建立一个项目,新建一个类,或者直接在 App_Code 里新建一个类,如下 :

    并在 Create 函数中设置一个断点。

     

     

    namespace  ConfigurationSectionTest
    {
        
    ///   <summary>
        
    /// WebSiteInfoHandler 的摘要说明
        
    ///   </summary>
         public   class  WebSiteInfoHandler : IConfigurationSectionHandler
        {
            
    public  WebSiteInfoHandler()
            {
                
    //
                
    // TODO: 在此处添加构造函数逻辑
                
    //

            }

            
    #region  IConfigurationSectionHandler 成员

            
    public   object  Create( object  parent,  object  configContext, System.Xml.XmlNode section)
            {
               
    // 这里我们首先返回个hello,并且在此处设置一个断点。看看程序什么时候执行到这。
                 return   " hello " ;
            }

            
    #endregion
        }

    }

     

    然后在 Default.aspx Page_Load 事件处理程序中去访问我们自定义的节点,并在 ConfigurationSettings.GetConfig("WebSiteInfo/basicInfo");  这条语句上设置断点。

    protected   void  Page_Load( object  sender, EventArgs e)
    {
        Object o 
    =  ConfigurationSettings.GetConfig( " WebSiteInfo/basicInfo " );
    }

    好了,我们启动调试,看到程序首先执行到 ConfigurationSettings.GetConfig("WebSiteInfo/basicInfo"); 这句。

    然后执行到 ConfigurationSectionTest.WebSiteInfoHandler 中的 Create 函数。

    我们再看看这时处理函数中参数的值:

    parent null

    configContext  为配置上下文对象。

    section  InnerXml <add key="name" value="huchen's homepage" /><add key="version" value="1.0" />


    按F11继续执行 return "hello", 继续执行...

    在执行到 Object o = ConfigurationSettings.GetConfig("WebSiteInfo/basicInfo") 后面的“ } “,我们发现 o 的值为 ”hello”

     

    相信您已经明白的差不多了,当读取自定义节点的内容时,程序去执行我们定义的节点处理程序,并把节点中的内容传给 Create 函数中的参数。然后我们在 Create 中自己处理节点下的内容,并返回我们格式化后的节点内容给调用者,也就是ConfigurationSettings.GetConfig( " WebSiteInfo/basicInfo " )。

    好,知道这些以后,我们就来完善我们的代码,我们在Create中处理传进来的节点内容。 

    为了简单起见,我们引入两个类 NameValueCollection NameValueSectionHandler

    NameValueCollection :表示可通过键或索引访问的关联   String  键和   String  值的集合。

    NameValueSectionHandler :提供配置节中的名称 / 值对配置信息。 NameValueSectionHandler  这个类也继承 IConfigurationSectionHandler
    反编译可以看出 NameValueSectionHandler  Create 方法把参数 section 的结果转化成了一个集合,就是 NameValueCollection

    那么我们可以在节点处理程序中的Create函数中写如下代码:

    NameValueCollection configs;
    NameValueSectionHandler baseHandler 
    =   new  NameValueSectionHandler();
    configs 
    = (NameValueCollection)baseHandler.Create(parent,configContext,section);
    Return configs;

    这样我们就可以这样访问我们的节点了:

    string  myWebSiteName  =  ((NameValueCollection)ConfigurationSettings.GetConfig( " WebSiteInfo/basicInfo " ))[ " name " ];

     

    Default.aspx Page_Load 事件处理程序中添加如下代码:

    string  myWebSiteName  =  ((NameValueCollection)ConfigurationSettings.GetConfig( " WebSiteInfo/basicInfo " ))[ " name " ];
    Response.Write(myWebSiteName);

     

    Ctrl+F5 运行,可以看到页面输出了 huchen's homepage

  • 相关阅读:
    SPOJ-BRCKTS (括号序列,线段树)
    bzoj 2223 [Coci 2009]PATULJCI
    bzoj 1049 [HAOI2006]数字序列
    bzoj2091 [Poi2010]The Minima Game
    bzoj 1016 [JSOI2008]最小生成树计数
    bzoj5105 晨跑 数论lcm
    bzoj 1211 [HNOI2004]树的计数
    bzoj 1430 小猴打架 prufer 性质
    Swing界面组件的通用属性
    数字调节控件JSpinner的使用
  • 原文地址:https://www.cnblogs.com/itjeff/p/4261856.html
Copyright © 2020-2023  润新知