我试图将app.config文件添加到我的DLL,但所有尝试都失败了.
根据MusicGenesis在" 将配置信息放入DLL中 "这应该不是问题.显然我做错了什么......
以下代码应该从我的DLL返回我的ConnectionString:
return ConfigurationManager.AppSettings["ConnectionString"];
但是,当我将app.config文件复制到我的控制台应用程序时,它工作正常.
有任何想法吗?
为.DLL创建.NET配置文件并非易事,这是有充分理由的..NET配置机制内置了许多功能,以便于轻松升级/更新应用程序,并保护已安装的应用程序不会践踏其他配置文件.
DLL的使用方式和应用程序的使用方式之间存在很大差异.您不可能在同一台计算机上为同一用户安装多个应用程序副本.但你可能有100个不同的应用程序或库都使用一些.NET DLL.
虽然有很少需要单独跟踪设置一个用户配置文件中的应用程序的不同副本,这是非常不可能的,你想全部DLL的不同用途的相互共享配置.因此,当您使用"普通"方法检索Configuration对象时,您获取的对象与您正在执行的App Domain的配置相关联,而不是特定的程序集.
App Domain绑定到根组件,该组件加载了代码实际所在的程序集.在大多数情况下,这将是主.EXE的程序集,这是加载.DLL的内容.可以在应用程序中启动其他应用程序域,但您必须明确提供有关该应用程序域的根程序集的信息.
由于这一切,创建特定于库的配置文件的过程不是那么方便.这与用于创建任何特定程序集的任意可移植配置文件的过程相同,但是您要使用.NET的XML模式,配置节和配置元素机制等.这需要创建一个ExeConfigurationFileMap
对象,加载数据以识别配置文件的存储位置,然后调用ConfigurationManager
.OpenMappedExeConfiguration
将其打开成一个新Configuration
实例.这将使您免受自动路径生成机制提供的版本保护.
从统计学上讲,您可能在内部设置中使用此库,并且您不可能在任何一台计算机/用户中使用多个应用程序. 但如果没有,你应该记住一些事情.如果对DLL使用单个全局配置文件,则无论引用它的应用程序如何,都需要担心访问冲突.如果引用您的库的两个应用程序恰好同时运行,每个应用程序都Configuration
打开了自己的对象,那么当一个应用程序保存更改时,下次您尝试在另一个应用程序中检索或保存数据时将导致异常.
解决此问题的最安全和最简单的方法是要求加载DLL的程序集也提供有关自身的一些信息,或通过检查引用程序集的App Domain来检测它.使用此选项可以创建某种文件夹结构,以便为引用DLL的每个应用程序保留单独的用户配置文件.
如果您确定要为DLL设置全局设置,无论它在何处被引用,您都需要确定它的位置,而不是.NET自动确定合适的DLL.您还需要积极管理对文件的访问.您需要尽可能多地进行缓存,只要保存Configuration
实例,只要加载或保存,在之前立即打开并在之后立即处理.最后,在使用该库的其中一个应用程序编辑文件时,您需要一个锁定机制来保护该文件.
如果你想从DLL的配置文件中读取设置,而不是从根应用程序web.config或app.config中读取设置,请使用下面的代码来读取dll中的配置.
var appConfig = ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location); string dllConfigData = appConfig.AppSettings.Settings["dllConfigData"].Value;
我有同样的问题,并在网上搜索了几个小时,但我找不到任何解决方案,所以我自己做了.我想知道为什么.net配置系统如此不灵活.
背景:我想让我的DAL.dll拥有自己的数据库和DAL设置配置文件.我还需要企业库的app.config及其自己的配置.所以我需要app.config和dll.config.
我不想做的是将每个属性/设置从应用程序传递到我的DAL层!
弯曲"AppDomain.CurrentDomain.SetupInformation.ConfigurationFile"是不可能的,因为我需要它用于正常的app.config行为.
我的要求/观点是:
没有从ClassLibrary1.dll.config到WindowsFormsApplication1.exe.config的任何手动副本,因为这对其他开发人员来说是不可复制的.
保留强类型"Properties.Settings.Default.NameOfValue"(设置行为)的使用,因为我认为这是一个主要功能,我不想失去它
我发现缺少ApplicationSettingsBase来注入您自己的/自定义配置文件或管理(所有必需的字段在这些类中都是私有的)
使用"configSource"文件重定向是不可能的,因为我们必须复制/重写ClassLibrary1.dll.config并为几个部分提供几个XML文件(我也不喜欢这个)
我不喜欢为MSDN建议的这个简单任务编写我自己的SettingsProvider,因为我觉得这太简单了
我只需要配置文件中的部分applicationSettings和connectionStrings
我想出了修改Settings.cs文件并实现了一个打开ClassLibrary1.dll.config并在私有字段中读取部分信息的方法.之后,我覆盖了"this [string propertyName]",因此生成的Settings.Desginer.cs调用我的新属性而不是基类.从列表中读出设置.
最后有以下代码:
internal sealed partial class Settings { private Listlist; /// /// Initializes a new instance of the public Settings() { this.OpenAndStoreConfiguration(); } ///class. /// /// Opens the dll.config file and reads its sections into a private List of ConfigurationElement. /// 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().ToList(); // read section of Connectionstrings var sections = config.Sections.OfType (); var connSection = (from section in sections where section.GetType() == typeof(ConnectionStringsSection) select section).FirstOrDefault() as ConnectionStringsSection; if (connSection != null) { list.AddRange(connSection.ConnectionStrings.Cast ()); } } /// /// Gets or sets the ///with the specified property name. /// 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中.
我知道这是晚会,但我想我会分享我用于DLL的解决方案.
我更喜欢KISS的思维学派,所以当我有一个想要存储外部数据点的.NET DLL来控制它的工作方式或它去的地方等等.我只是创建一个只有公共属性的"config"类.存储它需要的所有数据点,并且我希望能够控制DLL的外部以防止重新编译它以进行更改.然后我使用.Net的XML Serializing来保存并将类的对象表示加载到文件中.
有很多方法可以处理读取和访问它,从Singleton,静态实用程序类到扩展方法等.这取决于你的DLL的结构以及最适合你的DLL的方法.