2008-10-01 35 views
22

Realmente quiero poder tener una manera de tomar una aplicación que actualmente obtiene su configuración usando ConfigurationManager.AppSettings ["mysettingkey"] para que realmente esas configuraciones provengan de una base de datos centralizada en lugar del archivo app.config. Puedo hacer una sección de configuración personalizada para manejar este tipo de cosas, pero realmente no quiero que otros desarrolladores en mi equipo tengan que cambiar su código para usar mi nueva sección personalizada de DbConfiguration. Solo quiero que puedan llamar a AppSettings como lo han hecho siempre, pero que se carguen desde una base de datos central.¿Hay alguna manera de anular ConfigurationManager.AppSettings?

¿Alguna idea?

Respuesta

22

Si no te importa la piratería alrededor del marco y se puede suponer razonablemente que la versión de .NET Framework se ejecuta la aplicación en (es decir, se trata de una aplicación web o una aplicación de intranet), entonces usted podría intentar algo como esto:

using System; 
using System.Collections.Specialized; 
using System.Configuration; 
using System.Configuration.Internal; 
using System.Reflection; 

static class ConfigOverrideTest 
{ 
    sealed class ConfigProxy:IInternalConfigSystem 
    { 
    readonly IInternalConfigSystem baseconf; 

    public ConfigProxy(IInternalConfigSystem baseconf) 
    { 
     this.baseconf = baseconf; 
    } 

    object appsettings; 
    public object GetSection(string configKey) 
    { 
     if(configKey == "appSettings" && this.appsettings != null) return this.appsettings; 
     object o = baseconf.GetSection(configKey); 
     if(configKey == "appSettings" && o is NameValueCollection) 
     { 
     // create a new collection because the underlying collection is read-only 
     var cfg = new NameValueCollection((NameValueCollection)o); 
     // add or replace your settings 
     cfg["test"] = "Hello world"; 
     o = this.appsettings = cfg; 
     } 
     return o; 
    } 

    public void RefreshConfig(string sectionName) 
    { 
     if(sectionName == "appSettings") appsettings = null; 
     baseconf.RefreshConfig(sectionName); 
    } 

    public bool SupportsUserConfig 
    { 
     get { return baseconf.SupportsUserConfig; } 
    } 
    } 

    static void Main() 
    { 
    // initialize the ConfigurationManager 
    object o = ConfigurationManager.AppSettings; 
    // hack your proxy IInternalConfigSystem into the ConfigurationManager 
    FieldInfo s_configSystem = typeof(ConfigurationManager).GetField("s_configSystem", BindingFlags.Static | BindingFlags.NonPublic); 
    s_configSystem.SetValue(null, new ConfigProxy((IInternalConfigSystem)s_configSystem.GetValue(null))); 
    // test it 
    Console.WriteLine(ConfigurationManager.AppSettings["test"] == "Hello world" ? "Success!" : "Failure!"); 
    } 
} 
+6

reflexión privada ... muy travieso. –

+0

¿qué tiene que ver específicamente la versión .net framework con el ejemplo anterior? Es decir, estoy probando un ejemplo similar, pero aunque SetValue parece estar estableciendo el valor, al final, al tratar de recuperar la configuración falla, entonces, ¿en qué casos el código anterior podría no funcionar? gracias –

+2

El campo privado 's_configSystem' es un detalle de implementación de' ConfigurationManager' y podría cambiar en una futura versión del framework o podría no existir en absoluto (por ejemplo, mono tiene un campo llamado [configSystem] (https: // github. com/mono/mono/blob/effa4c07ba850bedbe1ff54b2a5df281c058ebcb/mcs/class/System.Configuration/System.Configuration/ConfigurationManager.cs # L48). –

0

No estoy seguro de que pueda anularlo, pero puede probar el método Agregar de AppSettings para agregar su configuración de base de datos cuando se inicien las aplicaciones.

1

Hagas lo que hagas, necesitarás agregar una capa de redirección? ConfigurationManager.AppSettings ["key"] siempre buscará en el archivo de configuración. Se puede hacer una ConfigurationFromDatabaseManager pero esto va a resultar en el uso de la sintaxis de llamada diferentes:

ConfigurationFromDatabaseManager.AppSettings["key"] instead of ConfigurationSettings["key"]. 
+2

creo que la razón de la cuestión es la necesidad de reemplazar el uso existente que es todo sobre el código para eliminar la necesidad de cambios extensos en la base de códigos. podría estar equivocado sin embargo. –

+1

Sin embargo, esta es la única solución limpia que existe (a menos que esté creando una aplicación web de Azure, donde puede establecer la configuración de la aplicación a través del Portal de Azure). –

-1

Parece que hay una manera de hacer esto en .NET 3.5 estableciendo el atributo allowOverride en la sección appsettings definición de machine.config. Esto le permite anular toda la sección en su propio archivo app.config y especificar un nuevo tipo para manejarlo.

+3

Creo que esto olvidó el objetivo de la pregunta. Mi lectura de la pregunta es cómo anular app.config, no cómo usar app.config para anular machine.config. –

0

Intentaré escribir un iniciador de aplicación y cargar la configuración de la base de datos al dominio de la aplicación. Entonces la aplicación no sabe nada sobre cómo se genera su configuración. El uso de machiene.config conduce directamente a dll-hell 2.0.

+0

¿De qué está hablando esta aplicación? –

0

Si usted puede guardar el archivo de configuración modificado en el disco - se puede cargar el archivo de configuración alternativo en diferentes dominio de aplicación:

AppDomain.CreateDomain("second", null, new AppDomainSetup 
{ 
    ConfigurationFile = options.ConfigPath, 
}).DoCallBack(...); 
Cuestiones relacionadas