2008-10-01 112 views
22

我真的希望能夠有一種方法來獲取當前使用ConfigurationManager.AppSettings [「mysettingkey」]獲取其設置的應用程序,實際上這些設置來自中央數據庫而不是app.config文件。我可以爲處理這種事情做一個自定義配置部分,但我真的不希望我的團隊中的其他開發人員必須更改他們的代碼以使用我的新DbConfiguration自定義部分。我只是希望他們能夠按照他們總是擁有的方式調用AppSettings,但可以從中央數據庫加載它。有沒有辦法來覆蓋ConfigurationManager.AppSettings?

任何想法?

回答

22

如果你不介意周圍的框架黑客和您可以合理假設應用程序上運行的.NET Framework版本(即它是一個Web應用程序或Intranet應用程序),那麼你可以嘗試這樣的事:

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

私人反思......非常調皮。 – 2011-03-04 21:47:49

0

我不確定您可以覆蓋它,但您可以嘗試應用程序啓動時添加AppSettings的方法來添加您的數據庫設置。

1

無論你做什麼,你都需要添加一層重定向? ConfigurationManager.AppSettings [「key」]將始終在配置文件中查找。你可以做一個ConfigurationFromDatabaseManager但是這會導致使用不同的調用語法:

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

我認爲這個問題的原因是覆蓋現有的使用情況是所有的需要通過代碼去除廣泛的代碼庫變化。可能是錯誤的。 – 2009-08-12 12:53:21

+1

然而,這是唯一存在的乾淨解決方案(除非您創建Azure Web應用程序,您可以通過Azure門戶設置應用程序設置)。 – 2017-04-20 14:40:30

-1

這似乎有一種方法通過設置在machine.config中的定義的appSettings節中有的allowOverride屬性來做到這一點.NET 3.5中。這使您可以覆蓋自己的app.config文件中的整個部分,並指定一個新類型來處理它。

+3

我認爲這錯過了這個問題的重點。我讀到的問題是如何覆蓋app.config,而不是如何使用app.config來覆蓋machine.config。 – 2013-02-01 18:34:05

0

我會嘗試編寫應用程序啓動程序並將數據庫中的設置加載到應用程序域。所以應用程序不知道它是如何生成配置的。 使用machiene.config直接導入到dll-hell 2.0。

0

如果你可以節省您修改配置文件保存到磁盤 - 你可以在不同的應用程序域加載的替代配置文件:

AppDomain.CreateDomain("second", null, new AppDomainSetup 
{ 
    ConfigurationFile = options.ConfigPath, 
}).DoCallBack(...); 
相關問題