自定义配置节:无法加载文件或程序集
我很难尝试访问我的配置文件中的自定义配置节。自定义配置节:无法加载文件或程序集
配置文件正在从作为插件加载的.dll中读取。我使用Configuration Section Designer VS插件创建了配置和必要的代码。
命名空间是'ImportConfiguration'。 ConfigurationSection类是'ImportWorkflows'。该程序集是ImportEPDMAddin。
的XML:
<configSections>
<section name="importWorkflows" type="ImportConfiguration.ImportWorkflows, ImportEPDMAddin"/>
</configSections>
每当我试着在配置读,我得到的错误:
出错创建importWorkflows配置节处理程序:无法加载文件或程序集“导入EPDMAddin.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以及也试过,但我得到一个异常说它无法加载文件或程序集“系统”。
我已经阅读了许多博客文章和文章,听起来像是可以读取一个dll的配置文件,但我无法让它工作。有任何想法吗?谢谢。
不幸的是,你要么需要有ImportEPDMAddin
组装居住在同一文件夹中可执行文件,驻留在关系到你使用(即C .NET Framework中的Net框架文件夹: \ Windows \ Microsoft.NET \ Framework \ v2.0.50727),或者在全局程序集缓存中注册。
唯一的其他选择,如果你知道的路径包含配置处理器的定义类的组件,你可以加载它没有像这样的东西的引用:
//Class global
private Assembly configurationDefiningAssembly;
protected TConfig GetCustomConfig<TConfig>(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事件,因为这会在没有它的情况下抛出异常。
非常非常感谢。这工作100%!! – ehcanadian 2009-11-05 20:21:00
这就像一个魅力,用于访问和投射T4文件中的自定义部分的类型。谢谢! – Matt 2014-10-22 21:14:12
@AJ。对不起,你能解释我什么是'configDefiningAssemblyPath' ..它是.exe文件吗? – Ciccio 2014-11-20 16:14:46
您是否确定首先加载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
此方法有效,但我希望坚持配置类。如果一切都失败了,我将不得不接受你的建议。 – ehcanadian 2009-11-05 19:15:38
在你的主应用程序的配置文件,添加以下(其中插件是为你的程序集,从加载的文件夹。您可以使用多个路径分号分隔。
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath=".;.\Plugins"/>
</assemblyBinding>
</runtime>
从http://msdn.microsoft.com/en-us/library/823z9h8w%28v=vs.90%29.aspx
请注意,只有在privatePath属性中指定的plugins文件夹是应用程序根目录的子目录时,才能使用探测来解决OP的问题。参见[msdn文档](http://msdn.microsoft.com/en-us/library/15hyw9x3(v = vs.110).aspx) – BitMask777 2015-01-06 19:13:46
为了扩大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");
}
我试图AJ的答案,与rileywhite的补充,但我发现,并没有为我工作。
在我的方案中,自定义的ConfigurationSection类已经在当前正在执行的程序集中,并且试图加载它会导致堆栈溢出。即使它确实解决了OP所报告的问题,但我也不想将其纳入GAC。
最后,我发现这个功能对我的目的来说已经足够了。也许别人会发现它有用:
public class CustomConfigurationSection : ConfigurationSection {
public CustomConfigurationSection()
{
var reader = XmlReader.Create(<path to my dll.config>);
reader.ReadToDescendant("CustomConfigurationSection");
base.DeserializeElement(reader,false);
}
// <rest of code>
}
不得不用我的模块/插件组装,这是在探测目录的完全合格的字符串类型,因此它可以被找到。使用的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"
你复制'ImportEPDMAddin.dll.config'到相同的位置吗? – ephemient 2009-11-05 18:49:44
配置是肯定的,因为我已经尝试从另一个类使用DictionarySectionHandler,并且工作。 – ehcanadian 2009-11-05 19:14:32