2010-04-27 13 views
74

¿Cómo creo una sección de app.config personalizada que es simplemente una lista simple de elementos add?Sección de app.config personalizada con una lista simple de elementos "agregar"

He encontrado algunos ejemplos (por ejemplo How to create custom config section in app.config?) para las secciones personalizadas que se ven así:

<RegisterCompanies> 
    <Companies> 
    <Company name="Tata Motors" code="Tata"/> 
    <Company name="Honda Motors" code="Honda"/> 
    </Companies> 
</RegisterCompanies> 

Pero ¿Cómo evito el elemento de recogida extra ("Empresas") para que se vea la lo mismo que las secciones appSettings y connectionStrings? En otras palabras, me gustaría:

<registerCompanies> 
    <add name="Tata Motors" code="Tata"/> 
    <add name="Honda Motors" code="Honda"/> 
</registerCompanies> 
+0

Cambie la etiqueta de su pregunta a C# 3.0 en lugar de C# 3.5 Vea aquí: http://stackoverflow.com/questions/247621/what-are-the-correct-version-numbers-for-c – Viper

+0

Heh, buen punto. –

+0

También vea http://stackoverflow.com/questions/1779117/how-to-get-a-liststring-collection-of-values-from-app-config-in-wpf –

Respuesta

95

Ejemplo completo con código basado en OP fichero de configuración:

<configuration> 
    <configSections> 
     <section name="registerCompanies" 
       type="My.MyConfigSection, My.Assembly" /> 
    </configSections> 
    <registerCompanies> 
     <add name="Tata Motors" code="Tata"/> 
     <add name="Honda Motors" code="Honda"/> 
    </registerCompanies> 
</configuration> 

Aquí es el código de ejemplo para implementar una sección de configuración personalizada con la colección colapsado

using System.Configuration; 
namespace My { 
public class MyConfigSection : ConfigurationSection { 
    [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)] 
    public MyConfigInstanceCollection Instances { 
     get { return (MyConfigInstanceCollection)this[""]; } 
     set { this[""] = value; } 
    } 
} 
public class MyConfigInstanceCollection : ConfigurationElementCollection { 
    protected override ConfigurationElement CreateNewElement() { 
     return new MyConfigInstanceElement(); 
    } 

    protected override object GetElementKey(ConfigurationElement element) { 
     //set to whatever Element Property you want to use for a key 
     return ((MyConfigInstanceElement)element).Name; 
    } 
} 

public class MyConfigInstanceElement : ConfigurationElement { 
    //Make sure to set IsKey=true for property exposed as the GetElementKey above 
    [ConfigurationProperty("name", IsKey = true, IsRequired = true)] 
    public string Name { 
     get { return (string) base["name"]; } 
     set { base["name"] = value; } 
    } 

    [ConfigurationProperty("code", IsRequired = true)] 
    public string Code { 
     get { return (string) base["code"]; } 
     set { base["code"] = value; } 
    } } } 

Aquí hay un ejemplo de cómo acceder a la información de configuración desde el código.

var config = ConfigurationManager.GetSection("registerCompanies") 
       as MyConfigSection; 

Console.WriteLine(config["Tata Motors"].Code); 
foreach (var e in config.Instances) { 
    Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
} 
+0

@Jay Walker ¿cómo se accede? el elemento que necesita, es decir: - config.Instances ["Tata Motors"] ¿es posible hacer esto? – Simon

+0

@Simon, consulte las actualizaciones de la respuesta, por ejemplo, uso. –

+0

¡Debería señalar que '' debería estar justo después de la etiqueta '' para que funcione! –

7

Según la respuesta de Jay Walker, debe acceder a los elementos iterando a través de la colección "Instancias". es decir.

var config = ConfigurationManager.GetSection("registerCompanies") 
       as MyConfigSection; 

foreach (MyConfigInstanceElement e in config.Instances) { 
    Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
} 
12

Basado en Jay Walker's respuesta anterior, esto es un ejemplo de trabajo completo que añade la capacidad de hacer la indexación:

<configuration> 
    <configSections> 
     <section name="registerCompanies" 
       type="My.MyConfigSection, My.Assembly" /> 
    </configSections> 
    <registerCompanies> 
     <add name="Tata Motors" code="Tata"/> 
     <add name="Honda Motors" code="Honda"/> 
    </registerCompanies> 
</configuration> 

Aquí está el código de ejemplo para implementar una sección de configuración personalizada con la colección colapsado

using System.Configuration; 
using System.Linq; 
namespace My 
{ 
    public class MyConfigSection : ConfigurationSection 
    { 
     [ConfigurationProperty("", IsRequired = true, IsDefaultCollection = true)] 
     public MyConfigInstanceCollection Instances 
     { 
     get { return (MyConfigInstanceCollection)this[""]; } 
     set { this[""] = value; } 
     } 
    } 
    public class MyConfigInstanceCollection : ConfigurationElementCollection 
    { 
     protected override ConfigurationElement CreateNewElement() 
     { 
     return new MyConfigInstanceElement(); 
     } 

     protected override object GetElementKey(ConfigurationElement element) 
     { 
     //set to whatever Element Property you want to use for a key 
     return ((MyConfigInstanceElement)element).Name; 
     } 

     public new MyConfigInstanceElement this[string elementName] 
     { 
     get 
     { 
      return this.OfType<MyConfigInstanceElement>().FirstOrDefault(item => item.Name == elementName); 
     } 
     } 
    } 

    public class MyConfigInstanceElement : ConfigurationElement 
    { 
     //Make sure to set IsKey=true for property exposed as the GetElementKey above 
     [ConfigurationProperty("name", IsKey = true, IsRequired = true)] 
     public string Name 
     { 
     get { return (string)base["name"]; } 
     set { base["name"] = value; } 
     } 

     [ConfigurationProperty("code", IsRequired = true)] 
     public string Code 
     { 
     get { return (string)base["code"]; } 
     set { base["code"] = value; } 
     } 
    } 
} 

Aquí hay un ejemplo de cómo acceder a la información de configuración desde el código.

MyConfigSection config = 
    ConfigurationManager.GetSection("registerCompanies") as MyConfigSection; 

Console.WriteLine(config.Instances["Honda Motors"].Code); 
foreach (MyConfigInstanceElement e in config.Instances) 
{ 
    Console.WriteLine("Name: {0}, Code: {1}", e.Name, e.Code); 
} 
19

No es necesaria la sección de configuración personalizada.

app.config

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
     <section name="YourAppSettings" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> 
    </configSections> 
    <!-- value attribute is optional. omit if you just want a list of 'keys' --> 
    <YourAppSettings> 
     <add key="one" value="1" /> 
     <add key="two" value="2"/> 
     <add key="three" value="3"/> 
     <add key="duplicate" value="aa"/> 
     <add key="duplicate" value="bb"/> 
    </YourAppSettings> 
</configuration> 

Recuperar

// This casts to a NameValueCollection because the section is defined as a 
/// AppSettingsSection in the configSections. 
NameValueCollection settingCollection = 
    (NameValueCollection)ConfigurationManager.GetSection("YourAppSettings"); 

var items = settingCollection.Count; 
Debug.Assert(items == 4); // no duplicates... the last one wins. 
Debug.Assert(settingCollection["duplicate"] == "bb"); 

// Just keys as per original question? done... use em. 
string[] allKeys = settingCollection.AllKeys; 

// maybe you did want key/value pairs. This is flexible to accommodate both. 
foreach (string key in allKeys) 
{ 
    Console.WriteLine(key + " : " + settingCollection[key]); 
} 
+1

Votos descendentes sin comentarios. Una viruela está contigo ... – JJS

+0

Supongo que no responde estrictamente la pregunta del OP, pero creo que es una solución válida, y mucho más simple. ¡Por lo menos me ayudó! – styl0r

+1

@ styl0r tienes razón. no * responde * estrictamente. Si tiene que usar los atributos nombre/código en lugar de mi clave/valor de solución, tendrá que usar una sección realmente personalizada. Sin embargo, asumo que tienes el control del archivo de configuración y tienes mejores cosas que hacer que crear una clase personalizada. – JJS

2

My.Assembly en config me dio excepción, porque puse el nombre de proyecto "Mi" y no "My.Assembly". ¡Ten cuidado, si usas este ejemplo!

Cuestiones relacionadas