Iva*_*vov 17 .net c# configuration configurationmanager
我的问题是关于使用标准.NET配置对象和自定义配置元素(可以通过扩展System.Configuration.ConfigurationSection类来定义).我们通常从System.Configuration.ConfigurationManager类的方法中获得这些,GetSection(...)作为一个例子.
加载的配置对象似乎是一个合并的配置对象,其中包含应用程序配置文件(开发人员可能创建的app.config或web.config文件)中存在的设置以及machine.config文件中定义的内容(后者随.NET Framework安装而来).
因此,我们可以假设首先使用machine.config以分层方式加载配置,并且任何用户定义的配置都覆盖默认设置,并且可以像这样查看:
我的目标是创建多层配置,以便在machine.config和app.config文件之间(如果可能,之后)之间可能存在其他配置文件:
更新
关键是 - 如果我在custom.config和app.config中定义了配置部分,我需要在调用时获得两个配置的合并版本ConfigurationManager.GetSection("MyCustomSection").理想情况下,如果我能够按照本MSDN文章中的描述执行合并,那将是很棒的.
通常,我会编写自己的配置管理器类,并尝试尽可能地获得所需的结果,但假设.NET框架对machine.config和app.config有效,我想我可能会受益于框架的内置功能.另外,我不知道如何手动触发这样的合并,如果我确实应该求助于我自己的配置管理器实现.
那么,是否可以利用配置部分/元素与自定义配置文件合并的内置机制?我特别感兴趣的是为自定义配置部分开发和支持它.该System.Configuration命名空间包含基础对象建立配置部分和元件,以及那些允许有关合并一些设置(如设置适当的ConfigurationElementCollectionType例如).这些是仅与machine.config(或Web应用程序中的多层web.config文件)合并,还是可以手动触发预加载配置文件的合并?我试图避免在任何自定义配置对象中支持自定义合并,并且可能忘记支持System.Configuration中的现有设置...
更新
根据现有的答案和评论,我想做一个重要的澄清.我能够ConfigurationSection从当前的应用程序设置(app.config/web.config)和我的custom.config物理文件加载对象.我需要知道是否有机会合并这些对象,而不需要通过框架中的一些内置方法进行反射和逐个属性比较.
注意:我希望能够更好地使用适用于.NET 3.0+的解决方案.如果您的答案针对更高版本的框架,请添加注释.
.NET配置系统不够灵活
这个评论指出了它,并解释了为什么你一直在寻找很长一段时间但还没有找到任何东西.并非所有的.NET Framework部件都是"好"的,System.Configuration值得在最底层找到它.对于那些最终是一项简单任务但同时又变得非常不灵活的东西来说,这是荒谬的过度设计.很难对这种情况进行逆向工程,我认为它因安全问题而陷入瘫痪.或许可以理解的是,用数据来征用一个程序总是存在相当大的风险.
我所知道的唯一扩展点是编写自己的SettingsProvider.该框架只有一个用于一般用途的LocalFileSettingProvider类.也非常不灵活,没有任何方法可以改变它的行为.自定义设置提供程序有一个不错的示例,RegistrySettingsProvider示例演示了一个在注册表中存储设置的提供程序.它可以是编写自己的好起点.
也许并不完全是你的想法,请抓住你可以进入System.Configuration内部分层的想法.
看一下下面的代码,它知道加载您的配置或 exe 配置。一旦您清楚了以下代码,您就可以根据需要自定义加载和合并(加载两次并用另一个覆盖一个)。
private static void InitConfiguration()
{
var map = new ExeConfigurationFileMap();
var AssemblyConfigFile = "";
if (File.Exists(AssemblyConfigFile))
map.ExeConfigFilename = AssemblyConfigFile;
else
map.ExeConfigFilename = Path.Combine(Environment.CurrentDirectory, Environment.GetCommandLineArgs()[0]+".config");
var Configuration = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var serviceModelSectionGroup = ServiceModelSectionGroup.GetSectionGroup(Configuration);
}
Run Code Online (Sandbox Code Playgroud)
正如白银指出的那样,配置良好的设备ExeConfigurationFileMap可以以一定的成本完成这项工作。
我以他为榜样,并做了一个可行的版本。
这是我出于测试目的而合并的两个配置文件:
custom.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="custom" type="..." />
</configSections>
<custom>
<singleProperty id="main" value="BaseValue" />
<propertyCollection>
<property id="1" value="One" />
<property id="4" value="Four" />
</propertyCollection>
</custom>
</configuration>
Run Code Online (Sandbox Code Playgroud)
app.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="custom" type="..."/>
</configSections>
<custom>
<singleProperty id="main" value="OverriddenValue" />
<propertyCollection>
<property id="1" value="OverridenOne" />
<property id="2" value="Two" />
<property id="3" value="Three" />
</propertyCollection>
</custom>
</configuration>
Run Code Online (Sandbox Code Playgroud)
我使用以下代码来测试合并的设置:
var map = new ExeConfigurationFileMap();
map.MachineConfigFilename = PathToCustomConfig;
map.ExeConfigFilename = PathToAppConfig;
var configuration = ConfigurationManager.OpenMappedExeConfiguration(
map,
ConfigurationUserLevel.None);
var section = configuration.GetSection("custom") as CustomConfigSection;
Assert.IsNotNull(section);
Assert.AreEqual(section.SingleProperty.Value, "OverriddenValue");
Assert.AreEqual(section.PropertyCollection.Count, 4);
// Needed to map the properties as dictionary, not to rely on the property order
var values = section.PropertyCollection
.Cast<SimpleConfigElement>()
.ToDictionary(x => x.ID, x => x.Value);
Assert.AreEqual(values["1"], "OverridenOne");
Assert.AreEqual(values["2"], "Two");
Assert.AreEqual(values["3"], "Three");
Assert.AreEqual(values["4"], "Four");
Run Code Online (Sandbox Code Playgroud)
map.MachineConfigFilename = PathToCustomConfig;我假设我要删除实际machine.config文件设置的所有值。这可能容易出错,并且对于Web应用程序应避免使用,因为它们大多数依赖于真实情况。machine.configapp.config编译代码时(通常是AssemblyName.exe.config)如何命名。我仍在完善技术,因此一旦完成,我将返回更新此帖子。