7

Estoy escribiendo un sistema de configuración en el que el archivo app.config se construye dinámicamente a partir de varios fragmentos de configuración distribuidos en varias ubicaciones. El sistema funciona actualmente de la siguiente manera:Obligar a ConfigurationManager a volver a cargar todas las secciones

  1. Bootstrapper crea el archivo de configuración.
  2. Bootstrapper inicializa el nuevo AppDomain con el nuevo archivo de configuración como archivo de configuración.
  3. Como resultado, el nuevo AppDomain está configurado para usar un nuevo archivo de configuración y todo funciona bien.

Nos gustaría alejarnos de este enfoque de dominio de aplicación múltiple; agrega una capa de complejidad, especialmente cuando se trata de bibliotecas no administradas y otros códigos heredados.

Al pasar a un dominio de aplicación, el flujo de trabajo cambiaría a:

  1. Bootstrapper construye archivo de configuración.
  2. Bootstrapper fusiona el archivo de configuración en su propio archivo de configuración.
  3. Bootstrapper actualiza su caché de ConfigurationManager.
  4. Bootstrapper inicia la aplicación principal en el mismo Dominio de aplicación.

Parece que ConfigurationManager almacena en caché secciones en la memoria. Entonces, por ejemplo, si leo AppSettings antes del paso 3, tengo que llamar al: ConfigurationManager.RefreshSection("appSettings"); De hecho, debo asegurarme de que cualquier sección que haya sido utilizada por el programa de arranque se actualice.

Puedo iterar sobre todas las secciones de configuración en el nuevo archivo de configuración y forzar su actualización, pero esto obliga al administrador de configuración a cargar cualquier ensamblaje al que se haga referencia en el archivo de configuración. Me gustaría diferir esto si es posible. Si hay una forma de invalidar lo que el ConfigurationManager tiene actualmente en la memoria?

Respuesta

0

Sé que la pregunta se publicó hace mucho tiempo, pero espero que esta respuesta siga siendo útil.

Parece que no hay una forma estándar de hacerlo. Sin embargo, al acceder a los campos internos y a los tipos de la clase ConfigurationManager, pude enumerar todas las secciones cargadas. Así es como lo hice:

private static IEnumerable<string> GetLoadedSections() 
{ 
    // s_configSystem can be null if the ConfigurationManager is not properly loaded. Accessing the AppSettings *should* do the trick. 
    var appSettings = ConfigurationManager.AppSettings; 

    FieldInfo s_configSystemField = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static); 
    object s_configSystem = s_configSystemField.GetValue(null); 
    FieldInfo _completeConfigRecordField = s_configSystem.GetType().GetField("_completeConfigRecord", BindingFlags.NonPublic | BindingFlags.Instance); 
    object _completeConfigRecord = _completeConfigRecordField.GetValue(s_configSystem); 
    FieldInfo _sectionRecordsField = _completeConfigRecord.GetType().GetField("_sectionRecords", BindingFlags.NonPublic | BindingFlags.Instance); 
    Hashtable _sectionRecords = (Hashtable)_sectionRecordsField.GetValue(_completeConfigRecord); 
    return _sectionRecords.Keys.OfType<string>(); 
} 

La sección "system.diagnostics" parece estar siempre cargada. La sección "appSettings" también se carga porque tengo que acceder a ella para que funcione de forma coherente.

Esto funciona en mi máquina (.NET 4.5) pero como se basa en elementos internos, puede romperse en cualquier momento si Microsoft decide cambiar la implementación de la clase ConfigurationManager.

Cuestiones relacionadas