2010-08-11 7 views
50

Estoy trabajando con C#, Framework 3.5 (VS 2008).Cómo obtener los valores de una sección de configuración de tipo NameValueSectionHandler

Estoy usando el ConfigurationManager para cargar una configuración (no el archivo predeterminado app.config) en un objeto de configuración.

Usando la clase de Configuración, pude obtener un ConfigurationSection, pero no pude encontrar una manera de obtener los valores de esa sección.

En la configuración, el ConfigurationSection es del tipo System.Configuration.NameValueSectionHandler.

Por lo que vale la pena, cuando utilicé el método de la GetSectionConfigurationManager (sólo funciona cuando estaba en mi archivo app.config por defecto), que recibieron un tipo de objeto, que podría echar en el conjunto de pares de número- valor, y acabo de recibir el valor como un Diccionario. No pude hacer tal molde cuando recibí la clase ConfigurationSection de la clase de Configuración sin embargo.

EDIT: Ejemplo del archivo de configuración:

<configuration> 
    <configSections> 
    <section name="MyParams" 
      type="System.Configuration.NameValueSectionHandler" /> 
    </configSections> 

    <MyParams> 
    <add key="FirstParam" value="One"/> 
    <add key="SecondParam" value="Two"/> 
    </MyParams> 
</configuration> 

ejemplo de la forma que era capaz de utilizarlo cuando estaba en app.config (el método "GetSection" es para el app.config predeterminado solamente):

NameValueCollection myParamsCollection = 
      (NameValueCollection)ConfigurationManager.GetSection("MyParams"); 

Console.WriteLine(myParamsCollection["FirstParam"]); 
Console.WriteLine(myParamsCollection["SecondParam"]); 
+0

¿Alguna vez una buena solución para esto? –

+0

Si estuviera usando .Net versión 4.0, entonces dynamic podría ayudar – Rahul

Respuesta

20

Here's una buena publicación que muestra cómo hacerlo.

Si desea leer los valores de un archivo que no sea el de app.config, debe cargarlo en el ConfigurationManager.

probar este método: ConfigurationManager.OpenMappedExeConfiguration()

Hay un ejemplo de cómo utilizarlo en el artículo de MSDN.

+4

Como dije en mi publicación, Esto es lo que hice. Recibí la clase de configuración, y de ella recibí una sección de configuración. Mi pregunta era ¿cómo puedo obtener los valores de ese objeto ConfigurationSection? No pregunté cómo obtener el objeto Configuración. ¡Gracias de todos modos! –

+2

por cierto, en el ejemplo que me dieron, no están utilizando la clase de configuración que viene de OpenMappedExeConfiguration, pero están usando el app.config predeterminado (que puede usarse con los métodos .GetSection/.GetConfig, pero como dije en mi post, ya lo hice, pero no es bueno para mí, ya que solo sirve para la configuración de aplicaciones). y para el msdn, no pude encontrar la respuesta a mi pregunta allí .. –

+0

Ok, cuanto más lo miro, más veo que no es fácil de hacer. El problema básico es que estás tratando de mezclar el código de estilo de configuración .Net 1.1 y 2.0. Lea esto, le indicará en la dirección correcta: http://www.eggheadcafe.com/software/aspnet/30832856/backwards-compatibility-of-systemconfigurationconfiguration.aspx – MonkeyWrench

10

Intente usar un AppSettingsSection en lugar de un NameValueCollection. Algo como esto:

var section = (AppSettingsSection)config.GetSection(sectionName); 
string results = section.Settings[key].Value; 

Fuente: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d5079420-40cb-4255-9b3b-f9a41a1f7ad2/

+4

, de esta manera obtendrá "No se puede convertir el objeto de tipo 'System.Configuration.DefaultSection' para escribir 'System.Configuration.AppSettingsSection'." – nerijus

+3

@nerijus: vamos hombre ... Por supuesto, una de las suposiciones de Steven es que realmente cambias el tipo de la sección en consecuencia ... Sin ánimo de ofender, pero realmente podrías pensar antes de comentar. Intenté esta solución y funciona. +1 para Steven – h9uest

+1

@ h9uest: No es tan sencillo, ya que Liran escribió que la sección es 'System.Configuration.NameValueSectionHandler'. Esta respuesta parece más una especie de hack sucio. –

15

Sufría de problema exacto. El problema fue debido a NameValueSectionHandler en el archivo .config. Debe utilizar AppSettingsSection lugar:

<configuration> 

<configSections> 
    <section name="DEV" type="System.Configuration.AppSettingsSection" /> 
    <section name="TEST" type="System.Configuration.AppSettingsSection" /> 
</configSections> 

<TEST> 
    <add key="key" value="value1" /> 
</TEST> 

<DEV> 
    <add key="key" value="value2" /> 
</DEV> 

</configuration> 

continuación, en C# código:

AppSettingsSection section = (AppSettingsSection)ConfigurationManager.GetSection("TEST"); 

por cierto NameValueSectionHandler No se admite más de 2,0.

+4

La función de conversión a AppSettings no funcionó. En cambio, me he convertido a NameValueCollection y funcionó. –

+0

@JonePolvora Yo también. –

1

Esta es una vieja pregunta, pero utilizo la siguiente clase para hacer el trabajo. Se basa en Scott Dorman's blog:

public class NameValueCollectionConfigurationSection : ConfigurationSection 
{ 
    private const string COLLECTION_PROP_NAME = ""; 

    public IEnumerable<KeyValuePair<string, string>> GetNameValueItems() 
    { 
     foreach (string key in this.ConfigurationCollection.AllKeys) 
     { 
      NameValueConfigurationElement confElement = this.ConfigurationCollection[key]; 
      yield return new KeyValuePair<string, string> 
       (confElement.Name, confElement.Value); 
     } 
    } 

    [ConfigurationProperty(COLLECTION_PROP_NAME, IsDefaultCollection = true)] 
    protected NameValueConfigurationCollection ConfCollection 
    { 
     get 
     { 
      return (NameValueConfigurationCollection) base[COLLECTION_PROP_NAME]; 
     } 
    } 

El uso es sencillo:

Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 
NameValueCollectionConfigurationSection config = 
    (NameValueCollectionConfigurationSection) configuration.GetSection("MyParams"); 

NameValueCollection myParamsCollection = new NameValueCollection(); 
config.GetNameValueItems().ToList().ForEach(kvp => myParamsCollection.Add(kvp)); 
6

La única manera que puedo conseguir que esto funcione es crear una instancia manualmente el tipo de controlador de sección, pasar el XML sin procesar a la misma, y lanzar el objeto resultante.

Parece bastante ineficiente, pero ahí lo tiene.

me escribió un método de extensión para encapsular esto:

public static class ConfigurationSectionExtensions 
{ 
    public static T GetAs<T>(this ConfigurationSection section) 
    { 
     var sectionInformation = section.SectionInformation; 

     var sectionHandlerType = Type.GetType(sectionInformation.Type); 
     if (sectionHandlerType == null) 
     { 
      throw new InvalidOperationException(string.Format("Unable to find section handler type '{0}'.", sectionInformation.Type)); 
     } 

     IConfigurationSectionHandler sectionHandler; 
     try 
     { 
      sectionHandler = (IConfigurationSectionHandler)Activator.CreateInstance(sectionHandlerType); 
     } 
     catch (InvalidCastException ex) 
     { 
      throw new InvalidOperationException(string.Format("Section handler type '{0}' does not implement IConfigurationSectionHandler.", sectionInformation.Type), ex); 
     } 

     var rawXml = sectionInformation.GetRawXml(); 
     if (rawXml == null) 
     { 
      return default(T); 
     } 

     var xmlDocument = new XmlDocument(); 
     xmlDocument.LoadXml(rawXml); 

     return (T)sectionHandler.Create(null, null, xmlDocument.DocumentElement); 
    } 
} 

La forma en que lo llamaría en su ejemplo es:

var map = new ExeConfigurationFileMap 
{ 
    ExeConfigFilename = @"c:\\foo.config" 
}; 
var configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None); 
var myParamsSection = configuration.GetSection("MyParams"); 
var myParamsCollection = myParamsSection.GetAs<NameValueCollection>(); 
0

Éstos son algunos ejemplos de this blog mencionados anteriormente:

<configuration>  
    <Database>  
     <add key="ConnectionString" value="data source=.;initial catalog=NorthWind;integrated security=SSPI"/>  
    </Database>  
</configuration> 

obtener valores:

NameValueCollection db = (NameValueCollection)ConfigurationSettings.GetConfig("Database");   
    labelConnection2.Text = db["ConnectionString"]; 

-

Otro ejemplo:

<Locations 
    ImportDirectory="C:\Import\Inbox" 
    ProcessedDirectory ="C:\Import\Processed" 
    RejectedDirectory ="C:\Import\Rejected" 
/> 

valor get:

Hashtable loc = (Hashtable)ConfigurationSettings.GetConfig("Locations"); 

labelImport2.Text = loc["ImportDirectory"].ToString(); 
labelProcessed2.Text = loc["ProcessedDirectory"].ToString(); 
Cuestiones relacionadas