Implements IConfigurationSectionHandler interface,create a custom configuration section handler

原帖地址:应用程序配置文件问题

配置文件如下:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="RinexHeader" type="System.Configuration.NameValueSectionHandler"/>
  </configSections>
  <RinexHeader>
    <!--O文件文件头标签字符串集合,和OHeaderLabel中的枚举值要一一对应-->
    <add key="OHeadLabel" value="RINEX VERSION / TYPE"/>
    <add key="OHeadLabel" value="PGM / RUN BY / DATE"/>
    <add key="OHeadLabel" value="COMMENT"/>
  </RinexHeader>
</configuration>

文中网友使用 NameValueSectionHandler 来处理 configuration section,他的问题是为什么 OHeadLabel  只取到一个,而不是多个。

这里要说明一下, NameValueSectionHandler 在处理 configuration section 的时候,使用的方式是

ReadOnlyNameValueCollectionInstance[key] = value;

这样相同 key 只会保留最后一个,之前的都会被覆盖掉。

所以在这里 NameValueSectionHandler 是不能胜任的。

还要说明下 NameValueSectionHandler  和 DictionarySectionHandler  除了在 GetSection 时返回类型不同外,基本相同。

因为 DictionarySectionHandler 返回的是哈希表,所以在大量节点的情况下后续查找的速度会比 NameValueSectionHandler 快。

为了实现需求,我们可以自定义 configuration section handler

思路很简单,在原本返回单个节点的属性值的地方返回集合。

具体代码如下:

public class CustomSectionHandler : IConfigurationSectionHandler
    {
        #region IConfigurationSectionHandler Members
        
        object IConfigurationSectionHandler.Create(
  object parent, object configContext, XmlNode section)
        {
            // Creates the configuration object that this method will return.
            // This can be a custom configuration class.
            // In this example, we use a System.Collections.Generic.IDictionary<string, IList<string>>.

            IDictionary<string, IList<IDictionary<string, string>>> myConfigObject = new Dictionary<string, IList<IDictionary<string, string>>>();

            // Gets any attributes for this section element.
            IDictionary<string, string> myAttribs = new Dictionary<string, string>();

            foreach (XmlAttribute attrib in section.Attributes)
            {
                if (XmlNodeType.Attribute == attrib.NodeType)
                    myAttribs.Add(attrib.Name, attrib.Value);
            }

            IList<IDictionary<string, string>> list = new List<IDictionary<string, string>>();

            // Puts the section name and attributes as the first config object item.
            list.Add(myAttribs);
            myConfigObject.Add(section.Name, list);

            // Gets the child element names and attributes.            
            foreach (XmlNode child in section.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    IDictionary<string, string> myChildAttribs = new Dictionary<string, string>();

                    foreach (XmlAttribute childAttrib in child.Attributes)
                    {
                        if (XmlNodeType.Attribute == childAttrib.NodeType)
                            myChildAttribs.Add(childAttrib.Name, childAttrib.Value);
                    }
                    if (myConfigObject.ContainsKey(myChildAttribs["key"]))
                    {
                        myConfigObject[myChildAttribs["key"]].Add(myChildAttribs);
                    }
                    else
                    {
                        list = new List<IDictionary<string, string>>();
                        list.Add(myChildAttribs);
                        myConfigObject.Add(myChildAttribs["key"], list);
                    }
                }
            }
            return (myConfigObject);
        }
        #endregion
    }

设置config

<configSections>
     <section name="RinexHeader" type="namespace.CustomSectionHandler,namespace, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"/>
</configSections>

调用代码

IDictionary<string, IList<IDictionary<string, string>>> dic = System.Configuration.ConfigurationManager.GetSection("RinexHeader") as Dictionary<string, IList<IDictionary<string, string>>>;

            if (dic.ContainsKey("OHeadLabel"))
            {
                foreach (var v in dic["OHeadLabel"])
                {
                    Console.WriteLine(v["value"]);
                }
            }

虽然实现了功能,但也暴露了问题 if (myConfigObject.ContainsKey(myChildAttribs["key"])) 可以看到 key 是硬编码在这的,这并不是一个好的实现。

而且配置文件中

<add key="OHeadLabel" value="RINEX VERSION / TYPE"/>
<add key="OHeadLabel" value="PGM / RUN BY / DATE"/>
<add key="OHeadLabel" value="COMMENT"/>

add 毫无意义,所以应改成

<OHeadLabel value="RINEX VERSION / TYPE"/>
<OHeadLabel value="PGM / RUN BY / DATE"/>
<OHeadLabel value="COMMENT"/>

然后修改之前的程序,myChildAttribs["key"]  =>  child.Name

修改后的代码:

 public class CustomSectionHandler : IConfigurationSectionHandler
    {
        #region IConfigurationSectionHandler Members

        object IConfigurationSectionHandler.Create(
  object parent, object configContext, XmlNode section)
        {
            // Creates the configuration object that this method will return.
            // This can be a custom configuration class.
            // In this example, we use a System.Collections.Generic.IDictionary<string, IList<string>>.

            IDictionary<string, IList<IDictionary<string, string>>> myConfigObject = new Dictionary<string, IList<IDictionary<string, string>>>();

            // Gets any attributes for this section element.
            IDictionary<string, string> myAttribs = new Dictionary<string, string>();

            foreach (XmlAttribute attrib in section.Attributes)
            {
                if (XmlNodeType.Attribute == attrib.NodeType)
                    myAttribs.Add(attrib.Name, attrib.Value);
            }

            IList<IDictionary<string, string>> list = new List<IDictionary<string, string>>();

            // Puts the section name and attributes as the first config object item.
            list.Add(myAttribs);
            myConfigObject.Add(section.Name, list);

            // Gets the child element names and attributes.            
            foreach (XmlNode child in section.ChildNodes)
            {
                if (XmlNodeType.Element == child.NodeType)
                {
                    IDictionary<string, string> myChildAttribs = new Dictionary<string, string>();

                    foreach (XmlAttribute childAttrib in child.Attributes)
                    {
                        if (XmlNodeType.Attribute == childAttrib.NodeType)
                            myChildAttribs.Add(childAttrib.Name, childAttrib.Value);
                    }
                    if (myConfigObject.ContainsKey(child.Name))
                    {
                        myConfigObject[child.Name].Add(myChildAttribs);
                    }
                    else
                    {
                        list = new List<IDictionary<string, string>>();
                        list.Add(myChildAttribs);
                        myConfigObject.Add(child.Name, list);
                    }
                }
            }
            return (myConfigObject);
        }
        #endregion
    }

大功告成。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值