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
    }

大功告成。

### Java中`implements`关键字与`interface`接口的关系 在Java编程语言中,`implements`关键字用于实现接口(interface)的功能。接口是一种特殊的抽象类,它定义了一组抽象方法和常量值,但不包含具体的方法实现或变量[^3]。 #### 1. **Interface 的定义与特性** - `interface` 是一种抽象类型,它包含了方法的签名(即方法声明),但没有具体的实现。 - 接口中所有方法默认是 `public` 和 `abstract` 的,即使没有显式声明。 - 接口可以包含常量,默认为 `public static final` 类型。 - Java 中的一个类只能单继承,但可以通过实现多个接口来模拟多重继承的效果[^2]。 ```java // 定义一个接口 public interface Animal { void speak(); // 抽象方法 int legs = 4; // 默认为 public static final } ``` #### 2. **Implements 的作用** - `implements` 关键字用于让某个类实现一个或多个接口中的方法。 - 实现接口时,必须提供接口中所有抽象方法的具体实现,否则该类也必须声明为抽象类。 - 通过 `implements`,类可以从接口中继承方法签名,并提供具体实现。 ```java // 实现接口的类 public class Dog implements Animal { @Override public void speak() { System.out.println("Bark"); } } ``` #### 3. **联系与区别** ##### 联系: - `interface` 是一种规范,定义了某些功能的行为;`implements` 是实现这些行为的方式。 - 通过 `implements`,类可以实现接口中的方法,从而遵循接口的规范[^3]。 ##### 区别: | 特性 | Interface | Implements | |-------------------|-----------------------------------|----------------------------------| | **定义** | 定义一组抽象方法和常量 | 表示类实现接口中的方法 | | **语法** | `public interface Name {}` | `public class Name implements {}` | | **多重继承支持** | 支持多重继承 | 不直接支持多重继承 | | **方法实现** | 只有方法签名,无具体实现 | 提供具体方法实现 | #### 4. **匿名内部类实现接口** 还可以通过匿名内部类的方式实现接口,这种方式通常用于简化代码[^1]。 ```java Animal animal = new Animal() { @Override public void speak() { System.out.println("Roar"); } }; animal.speak(); ``` --- ### 总结 `interface` 是一种抽象概念,定义了类需要遵循的规范,而 `implements` 是实现这些规范的具体手段。通过接口和 `implements`,Java 实现了类似多继承的功能,同时保持了语言设计的简洁性和一致性[^2]。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值