2009-07-18 9 views
9

Quiero leer la sección XML personalizada del app.config de un servicio de Windows C#.Cómo leer XML personalizado desde la aplicación.config?

¿Cómo lo hago?

El XML es el siguiente:

<Books> 
<Book name="name1" title="title1"/> 
<Book name="name2" title="title2"/> 
</Books> 
+0

Se ha perdido su XML o se tragó de alguna manera. –

+0

No te quedes atascado sobre cómo debe verse * XML * en app.config. Solo sé feliz de que funcione. – Will

Respuesta

5

Lo que se quiere hacer es leer sobre Custom Configuration Sections.

+1

¡Y buena suerte a los noobs que son lo suficientemente valientes como para hacer esto! Pueden ser muy confusos para un nuevo desarrollador. – Will

+2

Es cierto que la forma .NET 1.x donde implementó una interfaz y jugó con el XML fue mucho más fácil de entender, IMO. –

+2

Encontré este artículo serie en codeproject (http://www.codeproject.com/KB/dotnet/mysteriesofconfiguration.aspx) para ser una buena explicación sobre el tema. –

14

En un proyecto que desarrollé uso algo similar para la configuración que encontré. Creo que el artículo fue llamado el último controlador de sección de configuración que alguna vez necesitaré (no puedo encontrar un enlace que funcione, tal vez alguien pueda vincularlo para mí).

Este método lleva lo que usted desea dar un paso más allá, y realmente deserializa el objeto en la memoria. Solo estoy copiando el código de mi proyecto, pero debería ser bastante simple dar un paso atrás si lo único que quieres es el XML.

Primero, debe definir una clase que maneje sus configuraciones.

using System; 
using System.Configuration; 
using System.Xml; 
using System.Xml.Serialization; 
using System.Xml.XPath; 


namespace Ariel.config 
{ 
    class XmlSerializerSectionHandler : IConfigurationSectionHandler 
    { 

     #region IConfigurationSectionHandler Members 

     public object Create(object parent, object configContext, XmlNode section) 
     { 
      XPathNavigator nav = section.CreateNavigator(); 
      string typename = (string)nav.Evaluate("string(@type)"); 
      Type t = Type.GetType(typename); 
      XmlSerializer ser = new XmlSerializer(t); 
      return ser.Deserialize(new XmlNodeReader(section)); 
     } 

     #endregion 
    } 
} 

Ahora, supongamos que desea cargar una sección de configuración ... super fácil, fundido con el tipo de objeto que está esperando a XML Serialize a, y pasar la sección que está buscando (en SearchSettings este caso.

try 
{ 
    config = (Eagle.Search.SearchSettings)ConfigurationSettings.GetConfig("SearchSettings"); 
} 
catch (System.Configuration.ConfigurationException ex) 
{ 
    syslog.FatalException("Loading search configuration failed, you likely have an error", ex); 
    return; 
} 

Ahora, todo lo que necesita es su archivo app.config. elegí para dividir la mina en archivos separados (1 archivo por sección) sólo para hacer la gestión de la configuración un poco más fácil. se define una sección, asígnele un nombre y defina el tipo (como llame a la clase enumerada arriba) y el nombre del ensamblado.

App.config:

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
    <section name="SearchSettings" type="Ariel.config.XmlSerializerSectionHandler, Ariel"/> 
    </configSections> 
    <SearchSettings configSource="Config\Search.config" /> 
</configuration> 

Ahora, todo lo que queda es el archivo de configuración a ser serializado de-. Lo que es importante aquí es que el bloque coincide con el nombre de su sección, y su tipo es el objeto al que debe deserializar, y el nombre del ensamblado.

<?xml version="1.0" encoding="utf-8" ?> 
<SearchSettings type="Eagle.Search.SearchSettings, Eagle"> 
    <NumThreads>4</NumThreads> 
</SearchSettings> 

Si lo que desea es el XML prima pura, todo lo que necesitará hacer es modificar el objeto que se encarga de la sección de devolver el XML o hacer lo que tiene que hacer.

+1

Parece un enlace estable: http://sites.google.com/site/craigandera/craigs-stuff/clr-workings/thelastlast-configuration-section-handler-i-ll-ever-need. El único problema que veo con su enfoque es que si tienes un montón de tales secciones, se llenarán de declaraciones de tipo. Pero podrías evitar esta desventaja pegándolos en una sola sección y haciendo un tipo más grande. Como tal, parece bastante viable, y un truco bastante elegante. –

+0

¡Gracias! Esto fue muy útil. – JDPeckham

+0

Phil Haack hizo una versión actualizada basada en el enfoque de Craig que admite volver a cargar la configuración si el archivo cambia. El formato está roto en el cambio a su nuevo blog, pero el enlace es http://haacked.com/archive/2004/06/24/verylastconfigurationsectionhandler.aspx/ – piers7

0

Utilizo xml personalizado en mi config.app. archive y cree una aplicación. XSD a partir de ella. El archivo XSD incluye el esquema del archivo config.app. Luego, el archivo XSD se puede traducir a una clase vb o a un archivo de clase C# utilizando 'xsd.exe'. Ahora todo lo que tiene que hacer es deserializar el archivo de configuración para la clase.

<?xml version="1.0" encoding="utf-8" ?> 
<configuration> 
    <configSections> 
     <section name="CustomConfig" type="Object" /> 
    </configSections> 

    <CustomConfig> 
     <ActiveEnvironment>QAS</ActiveEnvironment> 
     <Environments> 
      <Environment name ="PRD" log="Y"> 
      </Environment> 
      <Environment name ="QAS" log="N"> 
      </Environment> 
      <Environment name ="DEV" log="Y"> 
      </Environment> 
     </Environments> 
    </CustomConfig> 

</configuration> 
+2

Poner tu tipo en Xml y luego autogenerar una clase parece bastante convincente. ¿Cómo se puede "crear una aplicación. XSD a partir de ella"? +1 cuando agrega esas instrucciones a su respuesta;) –

+0

Puede crear el XSD desde VS. Cree un archivo XML de muestra, luego en la barra de herramientas en VS2017, hay un menú 'XML' con la opción "Crear esquema". Más información en MSDN en https://msdn.microsoft.com/en-us/library/ms255829.aspx –

4

Desde IConfigurationSectionHandler es obsoleto pensé que vale la pena mencionar que todavía se puede poner en práctica una sección seriada pura simplemente reemplazando ConfigurationSection.DeserializeSection y no llamar a la implementación base.

Aquí hay un ejemplo muy básico que reutilizo mucho. Una sección de configuración simple que carga un gráfico de objetos desde XAML en línea.(Naturalmente puede implementar con XmlSerializer en su lugar)

using System.Configuration; 
using System.Xaml; 
using System.Xml; 

... 

public class XamlConfigurationSection<T> : ConfigurationSection 
{ 
    public static XamlConfigurationSection<T> Get(string sectionName) 
    { 
     return (XamlConfigurationSection<T>)ConfigurationManager.GetSection(sectionName); 
    } 

    public T Content { get; set; } 

    protected override void DeserializeSection(XmlReader xmlReader) 
    { 
     xmlReader.Read(); 
     using (var xamlReader = new XamlXmlReader(xmlReader)) 
      Content = (T)XamlServices.Load(xamlReader); 
    } 
} 
+0

+1 'ConfigurationSection.DeserializeSection' es un salvavidas ya que es más fácil iterar sobre el nodo XML cfg relevante en lugar de tratar w/System.Configuration varias anotaciones, y todavía exponer elementos de configuración estáticos/fuertemente seguros –

Cuestiones relacionadas