2008-10-01 184 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(...); 
相关问题