2008-10-01 32 views
22

Ich möchte wirklich eine Möglichkeit haben, eine App zu nehmen, die derzeit ihre Einstellungen unter Verwendung ConfigurationManager.AppSettings ["mysettingkey"] tatsächlich diese Einstellungen aus einer zentralen Datenbank anstelle der app.config-Datei kommen. Ich kann einen benutzerdefinierten Konfigurationsabschnitt für die Behandlung dieser Art von Sache erstellen, aber ich möchte wirklich nicht, dass andere Entwickler in meinem Team ihren Code ändern müssen, um meinen neuen benutzerdefinierten Abschnitt "DbConfiguration" zu verwenden. Ich möchte nur, dass sie AppSettings so aufrufen können, wie sie es immer tun, aber sie müssen aus einer zentralen Datenbank geladen werden.Gibt es eine Möglichkeit, ConfigurationManager.AppSettings zu überschreiben?

Irgendwelche Ideen?

Antwort

22

Wenn Sie nicht den Rahmen etwas dagegen, Hacking um und Sie können die Framework-Version davon ausgehen, die Anwendung läuft (dh es ist eine Web-Anwendung oder eine Intranet-Anwendung), dann Sie so etwas wie dies versuchen könnte:

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

private Reflexion ... sehr ungezogen. –

+0

Was hat die .net Framework-Version speziell mit dem obigen Beispiel zu tun? ... Ich probiere ein ähnliches Beispiel aus, aber obwohl SetValue den Wert zu setzen scheint, versucht der Versuch, die Konfigurationseinstellung abzurufen, am Ende - also, in welchen Fällen funktioniert der obige Code möglicherweise nicht? danke –

+2

Das private Feld 's_configSystem' ist ein Implementierungsdetail von 'ConfigurationManager' und könnte sich in einer zukünftigen Framework-Version ändern oder gar nicht existieren (zum Beispiel hat mono ein Feld namens [configSystem] (https: // github. com/mono/mono/blob/effa4c07ba850bedbe1ff54b2a5df281c058ebcb/mcs/Klasse/System.Configuration/System.Configuration/ConfigurationManager.cs # L48). –

0

Ich bin mir nicht sicher, ob Sie es überschreiben können, aber Sie können die Add-Methode von AppSettings versuchen, Ihre DB-Einstellungen beim Start der Anwendungen hinzuzufügen.

1

Was auch immer Sie tun müssen Sie eine Schicht Umleitung hinzufügen? ConfigurationManager.AppSettings ["Schlüssel"] wird immer in der Konfigurationsdatei suchen. Sie können eine ConfigurationFromDatabaseManager zu machen, aber dies mit unterschiedlicher Aufrufsyntax führt:

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

Ich denke, der Grund für die Frage der Notwendigkeit, die bestehende Nutzung außer Kraft zu setzen, die alle ist über den Code, um die Notwendigkeit für umfangreiche Code-Basisänderungen zu entfernen. könnte aber falsch sein. –

+1

Dies ist jedoch die einzige saubere Lösung, die existiert (es sei denn, Sie erstellen eine Azure-Webanwendung, in der Sie App-Einstellungen über das Azure-Portal festlegen können). –

-1

Es scheint, gibt es eine Möglichkeit, diese .NET 3.5, indem Sie das allowOverride Attribut in dem appSettings Definitionsabschnitt von machine.config zu tun in. Auf diese Weise können Sie den gesamten Abschnitt in Ihrer eigenen app.config-Datei überschreiben und einen neuen Typ für die Behandlung angeben.

+3

Ich denke, das hat den Punkt der Frage verfehlt. Ich habe die Frage gelesen, wie app.config überschrieben werden kann und nicht, wie app.config verwendet wird, um machine.config zu überschreiben. –

0

Ich würde versuchen, eine Anwendung Starter schreiben und laden Sie die Einstellungen von der Datenbank in die Anwendungsdomäne. Die App weiß also nichts darüber, wie ihre Konfiguration generiert wird. Die Verwendung von machiene.config führt direkt in dll-hell 2.0.

+0

Was ist das Anwendungsstarter-Ding, von dem Sie sprechen? –

0

Wenn Sie Sie modifizierte Konfigurationsdatei auf der Festplatte speichern können - können Sie die Datei alternative config in verschiedenen Anwendungsdomäne laden:

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