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

Posted

技术标签:

【中文标题】使用 ConfigurationManager 从任意位置加载配置【英文标题】:Using ConfigurationManager to load config from an arbitrary location 【发布时间】:2010-09-05 12:09:32 【问题描述】:

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

我想使用自定义的ConfigurationSection,对于 ASP.NET 页面,这非常有用。但是,当从经典 ASP 页面通过 COM 互操作调用组件时,组件不在 ASP.NET 请求的上下文中运行,因此不了解 web.config。

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

欢迎任何其他方法!

【问题讨论】:

见***.com/questions/3912727/… 这能回答你的问题吗? Change default app.config at runtime 【参考方案1】:

试试这个:

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

【讨论】:

我怎样才能以编程方式 为我在 sub.domain.com/virtualDir2 中的路径 C:\Portals\App1\v2配置文件 C:\Portals\App1\v2\web.config ? @Kiquenet:问题的关键在于 strConfigPath 是一个任意位置。换句话说,决定路径是什么,而不是依赖框架尝试从其常规位置加载配置文件。我假设Server.MapPath 会为您提供解决方案中任何文件的绝对位置。 也许var config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration("~/web.config"); @Kiquenet 绝对是。【参考方案2】:

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

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

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

例子:

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

更多详情请访问this blog。

另外,this other answer 有一个很好的解决方案,完整的代码刷新 应用程序配置和 IDisposable 对象将其重置为原始状态。有了这个 解决方案,您可以将临时应用配置保持在范围内:

using(AppConfig.Change(tempFileName))

    // tempFileName is used for the app config during this context

【讨论】:

这也适用于加载 web.config 文件。我使用它来加载 web.config 而不是 app.config 用于与任务相关的控制台应用程序。 ;) 这(以及此处的其他答案)对我不起作用。我在 program.cs 中添加了代码 - 函数:Main()。我的配置包含程序集版本重定向(请参阅***.com/questions/30165393/…),但手动更改配置时重定向不会影响。 你用过“APP_CONFIG_FILE”吗? 这是一个非常干净且易于实施的解决方案,对我有用。【参考方案3】:

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 设计者的意图使用这些功能。但是,这似乎对我有用。

【讨论】:

您还可以将 ConfigurationManager.OpenExeConfiguration (String) 重载用于相同目的。见:codeproject.com/KB/dotnet/mysteriesofconfiguration3.aspx#t2_1【参考方案4】:

接受的答案是错误的!!

访问 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);

【讨论】:

是的,这绝对是正确的答案!感谢您发布您的答案。 我认为 System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration 更正确,但它不适用于 .NET Core,所以在这种情况下,这个答案似乎可以完成。【参考方案5】:

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

【讨论】:

【参考方案6】:

我向 word 托管的 .nET Compoent 提供了配置值,如下所示。

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

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

【讨论】:

【参考方案7】:

对于 ASP.NET,使用 WebConfigurationManager:

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

【讨论】:

OpenWebConfiguration 的第一个参数就是路径(文件夹)。要指定文件名,您需要第二个参数【参考方案8】:

这应该可以解决问题:

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

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

【讨论】:

【参考方案9】:

使用 XML 处理:

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

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

【讨论】:

以上是关于使用 ConfigurationManager 从任意位置加载配置的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 configurationManager 从 .Net 4.0 中的 App.config 读取值?

ConfigurationManager.Read 从未知来源读取

使用 ConfigurationManager 将用户值存储在与应用配置不同的文件中

ConfigurationManager.AppSettings性能问题

C# ConfigurationManager 从 app.config 检索错误的连接字符串

如何在 Azure 的 ConfigurationManager.ConnectionStrings 上使用 ConnectionStrings 创建 EF 迁移?