自定义配置部分:无法加载文件或程序集
我在配置文件中尝试访问自定义配置部分非常困难。
正在从作为插件加载的.dll读取配置文件。 我使用Configuration Section Designer VS addin创建了配置和必要的代码。
命名空间是’ImportConfiguration’。 ConfigurationSection类是“ImportWorkflows”。 程序集是ImportEPDMAddin。
xml:
每当我尝试读取配置时,我都会收到错误:
为importWorkflow创建配置节处理程序时出错:无法加载文件或程序集“ImportEPDMAddin.dll”或其依赖项之一。 该系统找不到指定的文件。
dll不会与可执行文件驻留在同一目录中,因为加载插件的软件将dll和它的依赖项放在它自己的目录中。 (我无法控制它。)
我将单例实例的代码编辑为以下内容:
string path = System.Reflection.Assembly.GetCallingAssembly().CodeBase; path = path.Replace("file:///", ""); System.Configuration.Configuration configuration = System.Configuration.ConfigurationManager.OpenExeConfiguration(path); return configuration.GetSection(ImportWorkflowsSectionName) as ImportConfiguration.ImportWorkflows;
我也尝试过使用一个简单的NameValueFileSectionHandler,但我得到一个例外,说它无法加载文件或程序集’System’。
我已经阅读了大量的博客文章和文章,听起来有可能为dll读取配置文件,但我无法让它工作。 有任何想法吗? 谢谢。
不幸的是,您需要将ImportEPDMAddin
程序集与可执行文件驻留在同一文件夹中,驻留在与您正在使用的.Net框架相关的.Net框架文件夹中(即C:\ Windows \ Microsoft.NET \ Framework \ v2.0.50727),或在全局程序集缓存中注册。
唯一的另一个选择是,如果你知道包含配置处理程序的定义类的程序集的路径,你可以在没有引用的情况下加载它,如下所示:
//Class global private Assembly configurationDefiningAssembly; protected TConfig GetCustomConfig(string configDefiningAssemblyPath, string configFilePath, string sectionName) where TConfig : ConfigurationSection { AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(ConfigResolveEventHandler); configurationDefiningAssembly = Assembly.LoadFrom(configDefiningAssemblyPath); var exeFileMap = new ExeConfigurationFileMap(); exeFileMap.ExeConfigFilename = configFilePath; var customConfig = ConfigurationManager.OpenMappedExeConfiguration(exeFileMap, ConfigurationUserLevel.None); var returnConfig = customConfig.GetSection(sectionName) as TConfig; AppDomain.CurrentDomain.AssemblyResolve -= ConfigResolveEventHandler; return returnConfig; } protected Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args) { return configurationDefiningAssembly; }
确保你处理AssemblyResolve事件,因为这将抛出一个没有它的exception。
在主应用程序配置文件中,添加以下内容(其中插件是要从中加载程序集的文件夹。您可以使用分号分隔的多个路径。
摘自http://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.90%29.aspx
为了扩展AJ的优秀答案,这里有一个自定义类来协助注册和删除全局事件的开销。
public sealed class AddinCustomConfigResolveHelper : IDisposable { public AddinCustomConfigResolveHelper( Assembly addinAssemblyContainingConfigSectionDefinition) { Contract.Assert(addinAssemblyContainingConfigSectionDefinition != null); this.AddinAssemblyContainingConfigSectionDefinition = addinAssemblyContainingConfigSectionDefinition; AppDomain.CurrentDomain.AssemblyResolve += this.ConfigResolveEventHandler; } ~AddinCustomConfigResolveHelper() { this.Dispose(false); } public void Dispose() { this.Dispose(true); GC.SuppressFinalize(this); } private void Dispose(bool isDisposing) { AppDomain.CurrentDomain.AssemblyResolve -= this.ConfigResolveEventHandler; } private Assembly AddinAssemblyContainingConfigSectionDefinition { get; set; } private Assembly ConfigResolveEventHandler(object sender, ResolveEventArgs args) { // often the name provided is partial...this will match full or partial naming if (this.AddinAssemblyContainingConfigSectionDefinition.FullName.Contains(args.Name)) { return this.AddinAssemblyContainingConfigSectionDefinition; } return null; } }
我建议在using语句中创建一个实例,如下所示:
// you'll need to populate these two variables var configuration = GetConfiguration(); var assembly = GetAssemblyContainingConfig(); using(new AddinCustomConfigResolveHelper(assembly)) { return (MyConfigSection)configuration.GetSection("myConfigSection"); }
你能validation在主机应用程序的配置文件中是否正确设置了探测路径吗? 您当前的应用程序域中可能未加载所需的引用。
assembly绑定 – >探测
你确定首先加载了DLL吗? 也许使用Assembly.LoadFile("PATH")
?
如果无法使System.Configuration中的类正常工作,则可以始终使用XmlDocument手动解析配置文件。 使用XPath可以更轻松地获取数据。 例如(假设您的路径变量在上面):
var document = new XmlDocument(); document.Load(path); var node = document.SelectSingleNode("configuration/importWorkflows/add[@name='KEY']"); // Do whatever with node
我尝试了AJ的答案,有赖利白的补充,但我发现这对我不起作用。
在我的方案中,自定义ConfigurationSection类已经在当前正在执行的程序集中,并且尝试加载它会导致堆栈溢出。 我也不想把它放在GAC中,即使它确实解决了OP报告的问题。
最后,我发现这对我的目的来说足够好。 也许其他人会发现它很有用:
public class CustomConfigurationSection : ConfigurationSection { public CustomConfigurationSection() { var reader = XmlReader.Create(); reader.ReadToDescendant("CustomConfigurationSection"); base.DeserializeElement(reader,false); } // }
不得不使用我的模块/插件程序集的完全限定类型字符串,它位于探测目录中,因此可以找到它。 以EntityFramework为例……
不正确:
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework"
正确
type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
- 使用RDP 8.0的C#自定义远程桌面客户端
- 为什么我在尝试从正在写入的文件中读取时遇到未处理的exception:System.IO.IOException?
- Asp:net MVC 3:@ Html.Editor在模板中对我的模型进行子集合?
- PrintJob的实际总页数(Win32_PrintJob)
- 如何在ToolStrip Winforms控件的角落删除这个奇怪的视觉神器?
- entity framework在应该进行INNER JOIN(多个表)时生成LEFT OUTER JOIN
- 在“for”循环中添加委托更改迭代的方法 – C#问题?
- 如何在Windows窗体应用程序中实现控件validation?
- 字符串到变量名称