如何创建包含集合集的配置节?

时间:2012-06-09 03:08:42

标签: .net configuration system.configuration

我需要一个像这样的配置部分:

<myConfig>
    <mySubConfig1>
        <mySubSubConfig1 keyAttribute="value1">
            <mySubSubConfig1Element keyAttribute="value1"/>
            <mySubSubConfig1Element keyAttribute="value2"/>
        </mySubSubConfig1>
        <mySubSubConfig1 keyAttribute="value2">
            <mySubSubConfig1Element keyAttribute="value1"/>
        </mySubSubConfig1>
    </mySubConfig1>
    <mySubConfig2>
        <mySubSubConfig2 keyAttribute="value1">
            <mySubSubConfig2Element keyAttribute="value1"/>
            <mySubSubConfig2Element keyAttribute="value2"/>
        </mySubSubConfig2>
        <mySubSubConfig2 keyAttribute="value2">
            <mySubSubConfig2Element keyAttribute="value1"/>
        </mySubSubConfig2>
    </mySubConfig2>
    <mySubConfig3>
        <mySubSubConfig3 keyAttribute="value1">
            <mySubSubConfig3Element keyAttribute="value1"/>
            <mySubSubConfig3Element keyAttribute="value2"/>
        </mySubSubConfig3>
        <mySubSubConfig3 keyAttribute="value2">
            <mySubSubConfig3Element keyAttribute="value1"/>
        </mySubSubConfig3>
    </mySubConfig3>
</myConfig>

我还没有找到允许使用旧IConfigurationSectionHandler界面的魔法。有谁知道怎么做?

如果myConfigmySubConfignConfigurationSectionGroupConfigurationSection,我也可以。

此外,如果重要,这将在web.config中使用。

1 个答案:

答案 0 :(得分:68)

在您的示例配置文件中,myConfig将是一个继承自ConfigurationSection的类,其中包含三个名为mySubConfig1mySubConfig2mySubConfig3的属性。

mySubConfig1属性(以及2和3)的类型将是继承自ConfigurationElementCollection,实现IEnumerable<ConfigElement>并使用ConfigurationCollection修饰的类(其中“AddItemName”属性设置为“mySubSubConfig1”。

以下是我在生产部署中使用的方法的完整示例实现。请务必包含System.Configuration 程序集 。 (这有点令人困惑,因为System.Configuration命名空间在其他assmeblies中定义,但您必须包含System.Configuration 程序集才能使用下面的代码。)

以下是自定义配置类:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace ConfigTest {
    class CustomConfigSection : ConfigurationSection {

        [ConfigurationProperty( "ConfigElements", IsRequired = true )]
        public ConfigElementsCollection ConfigElements {
            get {
                return base["ConfigElements"] as ConfigElementsCollection;
            }
        }

    }

    [ConfigurationCollection( typeof( ConfigElement ), AddItemName = "ConfigElement" )]
    class ConfigElementsCollection : ConfigurationElementCollection, IEnumerable<ConfigElement> {

        protected override ConfigurationElement CreateNewElement() {
            return new ConfigElement();
        }

        protected override object GetElementKey( ConfigurationElement element ) {
            var l_configElement = element as ConfigElement;
            if ( l_configElement != null )
                return l_configElement.Key;
            else
                return null;
        }

        public ConfigElement this[int index] {
            get {
                return BaseGet( index ) as ConfigElement;
            }
        }

        #region IEnumerable<ConfigElement> Members

        IEnumerator<ConfigElement> IEnumerable<ConfigElement>.GetEnumerator() {
            return ( from i in Enumerable.Range( 0, this.Count )
                     select this[i] )
                    .GetEnumerator();
        }

        #endregion
    }

    class ConfigElement : ConfigurationElement {

        [ConfigurationProperty( "key", IsKey = true, IsRequired = true )]
        public string Key {
            get {
                return base["key"] as string;
            }
            set {
                base["key"] = value;
            }
        }

        [ConfigurationProperty( "SubElements" )]
        public ConfigSubElementsCollection SubElements {
            get {
                return base["SubElements"] as ConfigSubElementsCollection;
            }
        }

    }

    [ConfigurationCollection( typeof( ConfigSubElement ), AddItemName = "ConfigSubElement" )]
    class ConfigSubElementsCollection : ConfigurationElementCollection, IEnumerable<ConfigSubElement> {

        protected override ConfigurationElement CreateNewElement() {
            return new ConfigSubElement();
        }

        protected override object GetElementKey( ConfigurationElement element ) {
            var l_configElement = element as ConfigSubElement;
            if ( l_configElement != null )
                return l_configElement.Key;
            else
                return null;
        }

        public ConfigSubElement this[int index] {
            get {
                return BaseGet( index ) as ConfigSubElement;
            }
        }

        #region IEnumerable<ConfigSubElement> Members

        IEnumerator<ConfigSubElement> IEnumerable<ConfigSubElement>.GetEnumerator() {
            return ( from i in Enumerable.Range( 0, this.Count )
                     select this[i] )
                    .GetEnumerator();
        }

        #endregion
    }

    class ConfigSubElement : ConfigurationElement {

        [ConfigurationProperty( "key", IsKey = true, IsRequired = true )]
        public string Key {
            get {
                return base["key"] as string;
            }
            set {
                base["key"] = value;
            }
        }

    }


}

这是App.config文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <section name="CustomConfigSection" type="ConfigTest.CustomConfigSection,ConfigTest" />
  </configSections>

  <CustomConfigSection>
    <ConfigElements>
      <ConfigElement key="Test1">
        <SubElements>
          <ConfigSubElement key="-SubTest1.1" />
          <ConfigSubElement key="-SubTest1.2" />
        </SubElements>
      </ConfigElement>
      <ConfigElement key="Test2">
        <SubElements>
          <ConfigSubElement key="-SubTest2.1" />
          <ConfigSubElement key="-SubTest2.2" />
        </SubElements>
      </ConfigElement>
    </ConfigElements>
  </CustomConfigSection>

</configuration>

最后,这是访问和使用配置文件的代码:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Configuration;

namespace ConfigTest {
    class Program {
        static void Main( string[] args ) {

            var l_configSettings = (CustomConfigSection) ConfigurationManager.GetSection( "CustomConfigSection" );

            foreach ( var l_element in l_configSettings.ConfigElements.AsEnumerable() ) {
                Console.WriteLine( l_element.Key );

                foreach ( var l_subElement in l_element.SubElements.AsEnumerable() ) {
                    Console.WriteLine( l_subElement.Key );
                }

            }

            Console.WriteLine( "Press any key..." );
            Console.ReadKey( true );

        }
    }
}

Sunil Singh在他的博客上写了一个更轻量级的替代品:
http://blogs.quovantis.com/net-creating-a-custom-configuration-section-that-contains-a-collection-of-collections/