我有一个需要使用大量插件的程序。
每个插件必须支持一个非常基本的接口,此接口在DLL中定义(为了简单起见,IBaseComponent)。
每个插件都在特定目录中(AppDirectory \ plugin \ plugin-type)。 每个插件都可以有插件的dll的任何名称(AppDirectory \ plugin \ plugin-type \ plugin-name.dll)。
所以我需要检查每个plugin子目录,找到每个插件都有一个支持IBaseComponent接口的类,实例化该类并调用插件上的一些函数。
好吧,一切都很好,花花公子,这一切都不是特别难。但问题是我似乎遇到了一些奇怪的问题。每个插件都需要在各个插件文件夹中包含Base.dll文件(而不是仅在将要加载插件的程序中),而且似乎我在动态加载dll时会遇到很多错误和警告dll也需要加载。
我正在使用:
pluginModule = System.Reflection.Assembly.ReflectionOnlyLoadFrom(PathToAssembly);
为了获取插件dll并使用:
types = moduleAssembly.GetTypes();
以获取dll中包含的类型。 我正在遍历类型并检查单个类型是否属于IBaseComponent接口(表示这对于加载类是有效的):
if (type.GetInterface("FrameworkNameSpace.IBaseComponent") != null)
//it's of the IBaseComponent interface
稍后,为了从我使用的dll实际创建类的实例:
pluginModule = System.Reflection.Assembly.LoadFrom(PathToAssembly);
然后使用:
types = component.GetTypes();
为了获取模块中的类型,然后选择并加载支持与上面相同的接口的类。
当我使用时,问题似乎就出现了:
types = component.GetTypes();
当实际尝试加载课程时,而不是简单地看着它。 (因此我对 LoadFrom 和 ReflectionOnlyLoad 的不同用法)
我在GetTypes调用中收到的异常(在第二个插件上,但从来没有第一个!)是:
{"Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."}
将LoaderExceptions属性设置为:
{"The specified module could not be found. (Exception from HRESULT: 0x8007007E)":null}
我不确定为什么会这样。 DLL位于plugin文件夹中,包含IBaseComponent接口的DLL也位于每个插件目录中。我是以错误的方式解决这个问题吗?
我是否需要在每个插件子目录中保留包含IBaseComponent的DLL副本以及程序本身使用的副本,或者我是否正在做错误的操作以允许我删除此要求?
我知道MEF是我想要使用的,但不幸的是因为我需要在.net 2.0上支持这个。我无法使用MEF。
答案 0 :(得分:5)
这是LoadLibrary()失败。听我说你的插件依赖于一些非托管DLL。是的,Windows将很难找到这些DLL,它没有理由查看插件目录。也许它第一次工作,因为您的应用程序的默认目录恰好设置为正确的目录。这也是解决方法,使用Environment.CurrentDirectory。
确切地找出无法找到哪些依赖关系是关键。未管理的不会出现在fuslogvw.exe中,您可以从SysInternals的ProcMon实用程序中删除它。