[c#] Cambiar app.config predeterminado en el tiempo de ejecución



Answers

Puede intentar usar Configuration y Agregar ConfigurationSection en tiempo de ejecución

Configuration applicationConfiguration = ConfigurationManager.OpenMappedExeConfiguration(
                        new ExeConfigurationFileMap(){ExeConfigFilename = path_to_your_config,
                        ConfigurationUserLevel.None
                        );

applicationConfiguration.Sections.Add("section",new YourSection())
applicationConfiguration.Save(ConfigurationSaveMode.Full,true);

EDITAR: Aquí hay una solución basada en la reflexión (aunque no muy bonita)

Crear clase derivada de IInternalConfigSystem

public class ConfigeSystem: IInternalConfigSystem
{
    public NameValueCollection Settings = new NameValueCollection();
    #region Implementation of IInternalConfigSystem

    public object GetSection(string configKey)
    {
        return Settings;
    }

    public void RefreshConfig(string sectionName)
    {
        //throw new NotImplementedException();
    }

    public bool SupportsUserConfig { get; private set; }

    #endregion
}

luego, a través de la reflexión, configúralo en un campo privado en ConfigurationManager

        ConfigeSystem configSystem = new ConfigeSystem();
        configSystem.Settings.Add("s1","S");

        Type type = typeof(ConfigurationManager);
        FieldInfo info = type.GetField("s_configSystem", BindingFlags.NonPublic | BindingFlags.Static);
        info.SetValue(null, configSystem);

        bool res = ConfigurationManager.AppSettings["s1"] == "S"; // return true
Question

Tengo el siguiente problema:
Tenemos una aplicación que carga módulos (complementos). Estos módulos pueden necesitar entradas en la aplicación.config (por ejemplo, configuración WCF). Debido a que los módulos se cargan dinámicamente, no quiero tener estas entradas en el archivo app.config de mi aplicación.
Lo que me gustaría hacer es lo siguiente:

  • Cree una nueva app.config en la memoria que incorpore las secciones de configuración de los módulos
  • Dile a mi aplicación que use esa nueva app.config

Nota: ¡No quiero sobrescribir la aplicación predeterminada.config!

Debería funcionar de forma transparente, de modo que, por ejemplo, ConfigurationManager.AppSettings use ese nuevo archivo.

Durante mi evaluación de este problema, se me ocurrió la misma solución que aquí: recarga app.config con nunit .
Desafortunadamente, no parece hacer nada, porque todavía obtengo los datos de la aplicación normal .config.

Usé este código para probarlo:

Console.WriteLine(ConfigurationManager.AppSettings["SettingA"]);
Console.WriteLine(Settings.Default.Setting);

var combinedConfig = string.Format(CONFIG2, CONFIG);
var tempFileName = Path.GetTempFileName();
using (var writer = new StreamWriter(tempFileName))
{
    writer.Write(combinedConfig);
}

using(AppConfig.Change(tempFileName))
{
    Console.WriteLine(ConfigurationManager.AppSettings["SettingA"]);
    Console.WriteLine(Settings.Default.Setting);
}

Imprime los mismos valores twices, aunque combineConfig contiene otros valores que el app.config normal.




Daniel, si es posible intenta usar otros mecanismos de configuración. Hemos pasado por esta ruta en la que teníamos diferentes archivos de configuración estáticos / dinámicos según el entorno / perfil / grupo y al final se volvieron bastante complicados.

podría probar algún tipo de servicio web de perfil donde solo especifique una URL de servicio web del cliente y dependiendo de los detalles del cliente (puede tener anulaciones de nivel de grupo / usuario), carga todas las configuraciones que necesita. También hemos utilizado MS Enterprise Library para una parte de ella.

es decir, no implementas las configuraciones con tu cliente y puedes administrarlas separadamente de tus clientes




La solución de Daniel parece funcionar incluso para ensamblajes posteriores que había usado AppDomain.SetData antes, pero desconocía cómo restablecer los indicadores de configuración interna

Convertido a C ++ / CLI para aquellos interesados

/// <summary>
/// Remove cached values from ClientConfigPaths.
/// Call this after changing path to App.Config.
/// </summary>
void ResetConfigMechanism()
{
    BindingFlags Flags = BindingFlags::NonPublic | BindingFlags::Static;
    Type ^cfgType = ConfigurationManager::typeid;

    Int32 ^zero = gcnew Int32(0);
    cfgType->GetField("s_initState", Flags)
        ->SetValue(nullptr, zero);

    cfgType->GetField("s_configSystem", Flags)
        ->SetValue(nullptr, nullptr);

    for each(System::Type ^t in cfgType->Assembly->GetTypes())
    {
        if (t->FullName == "System.Configuration.ClientConfigPaths")
        {
            t->GetField("s_current", Flags)->SetValue(nullptr, nullptr);
        }
    }

    return;
}

/// <summary>
/// Use your own App.Config file instead of the default.
/// </summary>
/// <param name="NewAppConfigFullPathName"></param>
void ChangeAppConfig(String ^NewAppConfigFullPathName)
{
    AppDomain::CurrentDomain->SetData(L"APP_CONFIG_FILE", NewAppConfigFullPathName);
    ResetConfigMechanism();
    return;
}



Si su archivo de configuración se acaba de escribir con clave / valores en "appSettings", entonces puede leer otro archivo con dicho código:

System.Configuration.ExeConfigurationFileMap configFileMap = new ExeConfigurationFileMap();
configFileMap.ExeConfigFilename = configFilePath;

System.Configuration.Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(configFileMap, ConfigurationUserLevel.None);
AppSettingsSection section = (AppSettingsSection)configuration.GetSection("appSettings");

Luego puede leer la sección. Configuración como colección de KeyValueConfigurationElement.




Links