2010-05-12 21 views
34

Estoy tratando de usar ConfigurationManager.AppSettings.GetValues() para recuperar varios valores de configuración para una sola clave, pero siempre recibo una matriz de solo el último valor. Mi appsettings.config pareceMúltiples valores para una sola clave de configuración

<add key="mykey" value="A"/> 
<add key="mykey" value="B"/> 
<add key="mykey" value="C"/> 

y yo estoy tratando de acceder con

ConfigurationManager.AppSettings.GetValues("mykey"); 

pero yo sólo estoy poniendo { "C" }.

¿Alguna idea sobre cómo solucionar esto?

Respuesta

37

Trate

<add key="mykey" value="A,B,C"/> 

Y

string[] mykey = ConfigurationManager.AppSettings["mykey"].Split(','); 
+13

Entonces, ¿cuál es el sentido de 'ConfigurationManager.AppSettings.GetValues ​​() 'entonces? – Yuck

+0

@Yuck una preguntas el punto de la clase NameValueCollection subyacente - que soporta múltiples valores por clave, pero en realidad no permiten establecer más de una por tecla (AppSettings deben usar internamente el indexador set) - esta es la verdadera causa de la cuestión, en lugar de GetValues ​​() sólo devolver un solo valor. – fusi

+0

Si sólo hay un único valor, que no se encuentra ningún carácter se produce un error? –

6

Lo que quiere hacer no es posible. O bien debe nombrar cada clave de manera diferente, o hacer algo como value = "A, B, C" y separar los diferentes valores en el código string values = value.split(',').

Siempre recuperará el valor de la clave que se definió por última vez (en su ejemplo C).

9

La trata el archivo de configuración de cada línea como una misión, por lo que sólo se está viendo la última línea. Cuando lee la configuración, asigna a su llave el valor de "A", luego "B", luego "C", y dado que "C" es el último valor, es el que se pega.

como @Kevin sugiere, la mejor manera de hacer esto es probablemente un valor cuyos contenidos son un archivo CSV que se puede analizar por separado.

2

Dado que el método ConfigurationManager.AppSettings.GetValues() no está funcionando, he utilizado la siguiente solución para conseguir un efecto similar, pero con la necesidad de las teclas con el sufijo índices únicos.

var name = "myKey"; 
var uniqueKeys = ConfigurationManager.AppSettings.Keys.OfType<string>().Where(
    key => key.StartsWith(name + '[', StringComparison.InvariantCultureIgnoreCase) 
); 
var values = uniqueKeys.Select(key => ConfigurationManager.AppSettings[key]); 

Esto corresponderá con teclas como myKey[0] y myKey[1].

+0

ConfigurationManager.ConnectionStrings le da la capacidad de recorrer una lista que niega cualquier y todas las respuestas a esta pregunta (ya sé que no es la cadena de conexión por decir, pero se puede usar como tal) – user3036342

9

Sé que llego tarde pero encontré esta solución y funciona perfectamente, así que solo quiero compartirla.

Se trata de la definición de su propia ConfigurationElement

namespace Configuration.Helpers 
{ 
    public class ValueElement : ConfigurationElement 
    { 
     [ConfigurationProperty("name", IsKey = true, IsRequired = true)] 
     public string Name 
     { 
      get { return (string) this["name"]; } 
     } 
    } 

    public class ValueElementCollection : ConfigurationElementCollection 
    { 
     protected override ConfigurationElement CreateNewElement() 
     { 
      return new ValueElement(); 
     } 


     protected override object GetElementKey(ConfigurationElement element) 
     { 
      return ((ValueElement)element).Name; 
     } 
    } 

    public class MultipleValuesSection : ConfigurationSection 
    { 
     [ConfigurationProperty("Values")] 
     public ValueElementCollection Values 
     { 
      get { return (ValueElementCollection)this["Values"]; } 
     } 
    } 
} 

Y en el app.config sólo tiene que utilizar su nueva sección:

<configSections> 
    <section name="PreRequest" type="Configuration.Helpers.MultipleValuesSection, 
    Configuration.Helpers" requirePermission="false" /> 
</configSections> 

<PreRequest> 
    <Values> 
     <add name="C++"/> 
     <add name="Some Application"/> 
    </Values> 
</PreRequest> 

y cuando la recuperación de datos como este:

var section = (MultipleValuesSection) ConfigurationManager.GetSection("PreRequest"); 
var applications = (from object value in section.Values 
        select ((ValueElement)value).Name) 
        .ToList(); 

Finalmente, gracias al autor del original post

0

Aquí hay una solución completa: code in aspx.cs

namespace HelloWorld 
{ 
    public partial class _Default : Page 
    { 
     protected void Page_Load(object sender, EventArgs e) 
     { 
      UrlRetrieverSection UrlAddresses = (UrlRetrieverSection)ConfigurationManager.GetSection("urlAddresses"); 
     } 
    } 

    public class UrlRetrieverSection : ConfigurationSection 
    { 
     [ConfigurationProperty("", IsDefaultCollection = true,IsRequired =true)] 
     public UrlCollection UrlAddresses 
     { 
      get 
      { 
       return (UrlCollection)this[""]; 
      } 
      set 
      { 
       this[""] = value; 
      } 
     } 
    } 


    public class UrlCollection : ConfigurationElementCollection 
    { 
     protected override ConfigurationElement CreateNewElement() 
     { 
      return new UrlElement(); 
     } 
     protected override object GetElementKey(ConfigurationElement element) 
     { 
      return ((UrlElement)element).Name; 
     } 
    } 

    public class UrlElement : ConfigurationElement 
    { 
     [ConfigurationProperty("name", IsRequired = true, IsKey = true)] 
     public string Name 
     { 
      get 
      { 
       return (string)this["name"]; 
      } 
      set 
      { 
       this["name"] = value; 
      } 
     } 

     [ConfigurationProperty("url", IsRequired = true)] 
     public string Url 
     { 
      get 
      { 
       return (string)this["url"]; 
      } 
      set 
      { 
       this["url"] = value; 
      } 
     } 

    } 
} 

Y en web.config

<configSections> 
    <section name="urlAddresses" type="HelloWorld.UrlRetrieverSection" /> 
</configSections> 
<urlAddresses> 
    <add name="Google" url="http://www.google.com" /> 
    <add name="Yahoo" url="http://www.yahoo.com" /> 
    <add name="Hotmail" url="http://www.hotmail.com/" /> 
</urlAddresses> 
+0

Gracias CubeJockey para reallignment. –

0

Mi opinión sobre la respuesta de JJS: fichero de configuración:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="List1" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> 
    <section name="List2" type="System.Configuration.AppSettingsSection, System.Configuration, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" /> 
    </configSections> 
    <startup> 
     <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> 
    </startup> 
    <List1> 
    <add key="p-Teapot" /> 
    <add key="p-drongo" /> 
    <add key="p-heyho" /> 
    <add key="p-bob" /> 
    <add key="p-Black Adder" /> 
    </List1> 
    <List2> 
    <add key="s-Teapot" /> 
    <add key="s-drongo" /> 
    <add key="s-heyho" /> 
    <add key="s-bob"/> 
    <add key="s-Black Adder" /> 
    </List2> 

</configuration> 

código para recuperar en string []

private void button1_Click(object sender, EventArgs e) 
    { 

     string[] output = CollectFromConfig("List1"); 
     foreach (string key in output) label1.Text += key + Environment.NewLine; 
     label1.Text += Environment.NewLine; 
     output = CollectFromConfig("List2"); 
     foreach (string key in output) label1.Text += key + Environment.NewLine; 
    } 
    private string[] CollectFromConfig(string key) 
    { 
     NameValueCollection keyCollection = (NameValueCollection)ConfigurationManager.GetSection(key); 
     return keyCollection.AllKeys; 
    } 

IMO, eso es tan simple s se va a poner. No dude en para demostrar que estaba equivocado :)

0

Yo uso la convención de nombres de las teclas y funciona como un encanto

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <configSections> 
    <section name="section1" type="System.Configuration.NameValueSectionHandler"/> 
    </configSections> 
    <section1> 
    <add key="keyname1" value="value1"/> 
    <add key="keyname21" value="value21"/> 
    <add key="keyname22" value="value22"/> 
    </section1> 
</configuration> 

var section1 = ConfigurationManager.GetSection("section1") as NameValueCollection; 
for (int i = 0; i < section1.AllKeys.Length; i++) 
{ 
    //if you define the key is unique then use == operator 
    if (section1.AllKeys[i] == "keyName1") 
    { 
     // process keyName1 
    } 

    // if you define the key as a list, starting with the same name, then use string StartWith function 
    if (section1.AllKeys[i].Startwith("keyName2")) 
    { 
     // AllKeys start with keyName2 will be processed here 
    } 
} 
Cuestiones relacionadas