.net configuration system.configuration

.net - ¿Cómo crear una sección de configuración que contenga una colección de colecciones?



configuration system.configuration (1)

Necesito una sección de configuración como esta:

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

Todavía no he encontrado la magia que permitiría esto sin utilizar la antigua interfaz IConfigurationSectionHandler . Alguien sabe como hacerlo?

myConfig conmigo si myConfig y mySubConfign son ConfigurationSectionGroup o ConfigurationSection .

Además, si es importante, esto se usará desde web.config.


En su archivo de configuración de ejemplo, myConfig sería una clase que hereda de ConfigurationSection con tres propiedades llamadas mySubConfig1 , mySubConfig2 y mySubConfig3 .

El tipo de la propiedad mySubConfig1 (además de 2 y 3) sería una clase que hereda de ConfigurationElementCollection , implementa IEnumerable<ConfigElement> y está decorado con ConfigurationCollection (donde la propiedad "AddItemName" está configurada en "mySubSubConfig1").

A continuación se muestra una implementación de muestra completa de un enfoque que utilicé en una implementación de producción. Asegúrese de incluir el ensamblaje System.Configuration. (Es un poco confuso porque el espacio de nombres System.Configuration se define en otros assmeblies, pero debe incluir el ensamblado System.Configuration para usar el siguiente código).

Estas son las clases de configuración personalizadas:

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; } } } }

Aquí está el archivo 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>

Finalmente, aquí está el código que accede y usa el archivo de configuración:

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 escribió una alternativa más ligera en su blog:
http://blogs.quovantis.com/net-creating-a-custom-configuration-section-that-contains-a-collection-of-collections/