使用 ConfigurationManager 从任意位置加载配置

我正在开发一个数据访问组件,该组件将用于一个包含经典 ASP 和 ASP.NET 页面的网站,需要一个很好的方法来管理其配置设置。

我想使用一个自定义的 ConfigurationSection,并为 ASP.NET 页面这工作得很好。但是,当通过经典 ASP 页面的 COM 互操作调用该组件时,该组件不会在 ASP.NET 请求的上下文中运行,因此不知道 web.config。

有没有办法告诉 ConfigurationManager只是从任意路径加载配置(例如,如果我的程序集在 /bin文件夹中,就加载 ..\web.config) ?如果有,那么我认为我的组件可以回落到那,如果默认的 ConfigurationManager.GetSection返回 null为我的自定义部分。

我们欢迎任何其他方法来实现这一点!

109701 次浏览

试试这个:

System.Configuration.ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath); //Path to your config file
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedMachineConfiguration(fileMap);

除了 Ishmaeel 的回答之外,方法 OpenMappedMachineConfiguration()总是返回一个 Configuration对象。因此,要检查它是否加载,您应该检查 HasFile属性,其中 true 表示它来自文件。

Ishmaeel 的回答通常是有效的,但是我发现了一个问题,那就是使用 OpenMappedMachineConfiguration似乎会失去从 machine.config 继承的节组。这意味着您可以访问自己的自定义部分(这是所有 OP 需要的) ,但是不能访问普通的系统部分。例如,此代码将不起作用:

ConfigurationFileMap fileMap = new ConfigurationFileMap(strConfigPath);
Configuration configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns null

基本上,如果你在 configuration.SectionGroups上放一块手表,你会看到 system.net 没有注册为 SectionGroup,所以它几乎不能通过正常渠道访问。

我发现有两种方法可以解决这个问题。第一种方法是重新实现系统部分组,方法是将它们从 machine.config 复制到您自己的 web.config 例子中。

<sectionGroup name="system.net" type="System.Net.Configuration.NetSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<sectionGroup name="mailSettings" type="System.Net.Configuration.MailSettingsSectionGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<section name="smtp" type="System.Net.Configuration.SmtpSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
</sectionGroup>
</sectionGroup>

我不确定在那之后 Web 应用程序本身能否正确运行,但是您可以正确地访问 sectionGroups。

第二种解决方案是将 web.config 作为 EXE 配置打开,这可能更接近它的预期功能:

ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap() { ExeConfigFilename = strConfigPath };
Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
MailSettingsSectionGroup thisMail = configuration.GetSectionGroup("system.net/mailSettings") as MailSettingsSectionGroup;  // returns valid object!

我敢说这里提供的所有答案,无论是我的还是 Ishmaeel 的,都没有很好地使用这些函数。NET 设计器。但是,这似乎对我有用。

我像下面这样提供了 word 主机.nET 组件的配置值。

A.在 MSWord 中调用/托管 NET 类库组件。为了向组件提供配置值,我在 C: Program Files Microsoft Office Office11文件夹中创建了 winword.exe.config。您应该能够读取配置值,就像您在“传统”中所做的那样。NET.

string sMsg = System.Configuration.ConfigurationManager.AppSettings["WSURL"];

另一种解决方案是重写默认的环境配置文件路径。

我发现它是非平凡路径配置文件加载的最佳解决方案,特别是将配置文件附加到 dll 的最佳方法。

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", <Full_Path_To_The_Configuration_File>);

例如:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", @"C:\Shared\app.config");

详情请参阅 这个博客

此外,另一个答案有一个优秀的解决方案,完整的代码来刷新 应用程序配置和一个 IDisposable对象来重置它回到它的原始状态 解决方案,您可以保持临时应用程序配置的作用域:

using(AppConfig.Change(tempFileName))
{
// tempFileName is used for the app config during this context
}

对于 ASP.NET 使用 WebConfigurationManager:

var config = WebConfigurationManager.OpenWebConfiguration("~/Sites/" + requestDomain + "/");
(..)
config.AppSettings.Settings["xxxx"].Value;

使用 XML 处理:

var appPath = AppDomain.CurrentDomain.BaseDirectory;
var configPath = Path.Combine(appPath, baseFileName);;
var root = XElement.Load(configPath);


// can call root.Elements(...)

这应该会奏效:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "newAppConfig.config);

资料来源: https://www.codeproject.com/Articles/616065/Why-Where-and-How-of-NET-Configuration-Files

公认的答案是错误的! !

它在访问 AppSettings 属性时引发以下异常:

无法将“ System.Configuration. DefaultSection”类型的对象强制转换为“ System.Configuration. AppSettingsSection”类型。

以下是正确的解决方案:

System.Configuration.ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = "YourFilePath";
System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);