我真的希望能够有一种方法来获取当前使用ConfigurationManager.AppSettings["mysettingkey"]获取其设置的应用程序,以使这些设置实际上来自集中式数据库而不是 app.config 文件。我可以制作一个自定义配置部分来处理这类事情,但我真的不希望我团队中的其他开发人员不得不更改他们的代码来使用我的新 DbConfiguration 自定义部分。我只是希望他们能够以他们一直使用的方式调用 AppSettings,但可以从中央数据库加载它。
有任何想法吗?
我真的希望能够有一种方法来获取当前使用ConfigurationManager.AppSettings["mysettingkey"]获取其设置的应用程序,以使这些设置实际上来自集中式数据库而不是 app.config 文件。我可以制作一个自定义配置部分来处理这类事情,但我真的不希望我团队中的其他开发人员不得不更改他们的代码来使用我的新 DbConfiguration 自定义部分。我只是希望他们能够以他们一直使用的方式调用 AppSettings,但可以从中央数据库加载它。
有任何想法吗?
如果您不介意围绕框架进行黑客攻击,并且可以合理地假设应用程序正在运行的 .net 框架版本(即它是 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!");
}
}
无论您做什么,都需要添加一层重定向?ConfigurationManager.AppSettings["key"] 将始终查看配置文件。您可以创建 ConfigurationFromDatabaseManager 但这将导致使用不同的调用语法:
ConfigurationFromDatabaseManager.AppSettings["key"] instead of ConfigurationSettings["key"].
我不确定您是否可以覆盖它,但您可以尝试 AppSettings 的 Add 方法在应用程序启动时添加您的数据库设置。
我会尝试编写一个应用程序启动器并将设置从数据库加载到应用程序域。所以应用程序不知道它的配置是如何生成的。使用 machiene.config 直接进入 dll-hell 2.0。
如果您可以将修改后的配置文件保存到磁盘 - 您可以在不同的应用程序域中加载替代配置文件:
AppDomain.CreateDomain("second", null, new AppDomainSetup
{
ConfigurationFile = options.ConfigPath,
}).DoCallBack(...);
似乎有一种方法可以在 .NET 3.5 中通过在 machine.config 的 appSettings 定义部分中设置 allowOverride 属性来执行此操作。这允许您覆盖您自己的 app.config 文件中的整个部分并指定一个新类型来处理它。