我试图将一个app.config文件添加到我的DLL中,但所有尝试都失败了。
根据MusicGenesis在“将配置信息放入DLL”中的说法,这应该不是问题。所以显然我做错了什么...
以下代码应该从我的DLL中返回我的ConnectionString:
return ConfigurationManager.AppSettings["ConnectionString"];
然而,当我将app.config文件复制到我的控制台应用程序中时,它可以正常工作。
有任何想法吗?
我试图将一个app.config文件添加到我的DLL中,但所有尝试都失败了。
根据MusicGenesis在“将配置信息放入DLL”中的说法,这应该不是问题。所以显然我做错了什么...
以下代码应该从我的DLL中返回我的ConnectionString:
return ConfigurationManager.AppSettings["ConnectionString"];
然而,当我将app.config文件复制到我的控制台应用程序中时,它可以正常工作。
有任何想法吗?
从统计学的角度来看,你可能正在使用这个库在公司内部设置中,不太可能在同一台机器/用户上有多个应用程序在使用它。 但是如果不是这样的话,你需要记住一些事情。 如果你针对你的DLL使用单个全局配置文件,无论引用它的应用程序是什么,你都需要担心访问冲突。 如果两个引用你的库的应用程序恰好同时运行,并且每个应用程序都有自己打开的Configuration
对象,那么当一个应用程序保存更改时,它将导致下次尝试在另一个应用程序中检索或保存数据时出现异常。
最安全、最简单的方法是要求加载你的DLL的程序集也提供一些关于它自己的信息,或者通过检查引用程序集的应用程序域来检测它。 使用这个信息来创建某种文件夹结构,为每个引用你的DLL的应用程序保留单独的用户配置文件。
如果你确信想要在任何地方引用DLL都有全局设置,那么你需要确定它的位置,而不是.NET自动找到适当的位置。 你还需要积极地管理文件访问权限。 尽可能地缓存,仅在加载或保存时保留Configuration
实例,立即打开和释放。 最后,你需要一个锁定机制来保护在使用库的某个应用程序编辑文件时。
如果你想从DLL的配置文件中读取设置,但不想从根应用程序的web.config或app.config中读取,请使用以下代码来读取dll中的配置。
var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location);
string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;
internal sealed partial class Settings
{
private List<ConfigurationElement> list;
/// <summary>
/// Initializes a new instance of the <see cref="Settings"/> class.
/// </summary>
public Settings()
{
this.OpenAndStoreConfiguration();
}
/// <summary>
/// Opens the dll.config file and reads its sections into a private List of ConfigurationElement.
/// </summary>
private void OpenAndStoreConfiguration()
{
string codebase = System.Reflection.Assembly.GetExecutingAssembly().CodeBase;
Uri p = new Uri(codebase);
string localPath = p.LocalPath;
string executingFilename = System.IO.Path.GetFileNameWithoutExtension(localPath);
string sectionGroupName = "applicationSettings";
string sectionName = executingFilename + ".Properties.Settings";
string configName = localPath + ".config";
ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
fileMap.ExeConfigFilename = configName;
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
// read section of properties
var sectionGroup = config.GetSectionGroup(sectionGroupName);
var settingsSection = (ClientSettingsSection)sectionGroup.Sections[sectionName];
list = settingsSection.Settings.OfType<ConfigurationElement>().ToList();
// read section of Connectionstrings
var sections = config.Sections.OfType<ConfigurationSection>();
var connSection = (from section in sections
where section.GetType() == typeof(ConnectionStringsSection)
select section).FirstOrDefault() as ConnectionStringsSection;
if (connSection != null)
{
list.AddRange(connSection.ConnectionStrings.Cast<ConfigurationElement>());
}
}
/// <summary>
/// Gets or sets the <see cref="System.Object"/> with the specified property name.
/// </summary>
/// <value></value>
public override object this[string propertyName]
{
get
{
var result = (from item in list
where Convert.ToString(item.ElementInformation.Properties["name"].Value) == propertyName
select item).FirstOrDefault();
if (result != null)
{
if (result.ElementInformation.Type == typeof(ConnectionStringSettings))
{
return result.ElementInformation.Properties["connectionString"].Value;
}
else if (result.ElementInformation.Type == typeof(SettingElement))
{
return result.ElementInformation.Properties["value"].Value;
}
}
return null;
}
// ignore
set
{
base[propertyName] = value;
}
}
您只需要将ClassLibrary1.dll.config从ClassLibrary1输出目录复制到应用程序的输出目录。
也许有人会觉得这很有用。
使用 ConfigurationManager 时,我相信它会加载进程/ AppDomain
配置文件(app.config / web.config)。 如果您想加载特定的配置文件,您需要明确使用该文件的名称进行请求...
您可以尝试:
var config = ConfigurationManager.OpenExeConfiguration("foo.dll");
config.ConnectionStrings. [etc]
ConfigurationManager.AppSettings返回应用程序定义的设置,而不是特定DLL的设置,可以访问它们,但将返回应用程序设置。
如果您从另一个应用程序使用dll,则ConnectionString应该在应用程序的app.settings中。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="yourKeyName" value="yourKeyValue"/>
</appSettings>
</configuration>
4) 将 System.Configuration 添加到您的 dll/class/project 引用中
5) 在您打算访问配置设置的代码中添加 using 语句
using System.Configuration;
using System.Reflection;
6) 访问值
string keyValue = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings.Settings["yourKeyName"].Value;
7) 喜大普奔,它能正常工作了
我认为,这只应该在开发新的dll/库时使用。
#if (DEBUG && !FINALTESTING)
string keyValue = ConfigurationManager.OpenExeConfiguration...(see 6 above)
#else
string keyValue = ConfigurationManager.AppSettings["yourKeyName"];
#endif
你是正确的,你可以读取dll文件的配置文件。我曾经为此苦苦挣扎了一天,直到发现我的配置文件有问题。看看下面的代码,它能够运行。
ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = Assembly.GetExecutingAssembly().Location + ".config";
Configuration libConfig = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
AppSettingsSection section = (libConfig.GetSection("appSettings") as AppSettingsSection);
Console.WriteLine(section.Settings["dnd_shortcodes"].Value);
我的Plugin1.dll.config
文件如下所示:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="cmd_location" value="http://..."/>
<add key="dnd_shortcodes" value="142,145,146,157,165,167,168,171,173,176,178,404,40"/>
</appSettings>
</configuration>
<appSettings>
标签,所以请仔细查找,你的问题可能不同于我,但也不会差太远。如果你正在使用查找大量配置的库,比如WCF,你可以考虑做以下操作:
AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", "MyWcfClientWrapper.dll.config");
或者在PowerShell中:
[AppDomain]::CurrentDomain.SetData("APP_CONFIG_FILE", "MyWcfClientWrapper.dll.config")
在IT技术中,我认为这种技巧是一种“代码异味”,只适合在临时脚本中使用。如果你发现自己想在生产代码中使用它,也许是时候进行架构审查了。
不推荐以下做法:
作为一种技术上的好奇心,这里有一个变体。你可以在DLL中的一个类中创建一个静态构造函数,并从那里调用它。除非万不得已,否则我不建议这样做。
由于程序集驻留在临时缓存中,因此您应将路径组合起来获取dll的配置:
var appConfig = ConfigurationManager.OpenExeConfiguration(
Path.Combine(Environment.CurrentDirectory, Assembly.GetExecutingAssembly().ManifestModule.Name));