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

How to Create a Configuration Section That Contains a Collection of Collections?

提问人:John Saunders 提问时间:6/9/2012 更新时间:1/21/2016 访问量:21965

问:

我需要一个配置部分,如下所示:

<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 中使用。

.NET 配置 系统.configuration

评论


答:

70赞 JDB 11/6/2012 #1

在您的示例配置文件中,将是一个继承自的类,具有三个名为 和 的属性。myConfigConfigurationSectionmySubConfig1mySubConfig2mySubConfig3

属性的类型(以及 2 和 3)将是一个继承自 、实现和修饰的类(其中“AddItemName”属性设置为“mySubSubConfig1”)。mySubConfig1ConfigurationElementCollectionIEnumerable<ConfigElement>ConfigurationCollection

下面是我在生产部署中使用的方法的完整示例实现。请确保包括 System.Configuration 程序集。(这有点令人困惑,因为 System.Configuration 命名空间是在其他组合中定义的,但您必须包括 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 文件:Here's the App.config file:

<?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/

评论

1赞 nmase88 10/20/2022
谢谢!我已经试图弄清楚这个问题好几个小时了!似乎添加带有 AddElementName 的构造函数是关键,因为我其他一切都正确。