我有一个需要使用大量插件的程序。
每个插件都必须支持一个非常基本的接口(interface),这个接口(interface)是在一个 DLL 中定义的(为简单起见,IBaseComponent)。
每个插件都在一个特定的目录中(AppDirectory\plugin\plugin-type)。 每个插件都可以为插件的 dll (AppDirectory\plugin\plugin-type\plugin-name.dll) 取任何名称。
所以我需要检查每个插件子目录,找到每个插件都有一个支持 IBaseComponent 接口(interface)的类,实例化该类并调用插件上的一些函数。
好的,一切都很好,这些都不是特别难。但问题是我似乎遇到了一些奇怪的问题。
每个插件都需要在单独的插件文件夹中有 Base.dll 文件(而不是仅仅在将要加载插件的程序中)而且似乎我在动态加载一个 dll 时收到很多错误和警告,其中有还需要加载的 dll。
我正在使用:
pluginModule = System.Reflection.Assembly.ReflectionOnlyLoadFrom(PathToAssembly);
为了获取插件 dll 并使用:
types = moduleAssembly.GetTypes();
为了获取 dll 中包含的类型。 我正在迭代类型并检查单个类型是否属于 IBaseComponent 接口(interface)(表示这是一个有效的加载类):
if (type.GetInterface("FrameworkNameSpace.IBaseComponent") != null)
//it's of the IBaseComponent interface
稍后,为了从我使用的 dll 中实际创建类的实例:
pluginModule = System.Reflection.Assembly.LoadFrom(PathToAssembly);
然后使用:
types = component.GetTypes();
为了获取模块中的类型,然后选择并加载支持与上述接口(interface)相同的类。
问题似乎是在我使用时出现的:
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 在插件文件夹中,包含 IBaseComponent 接口(interface)的 DLL 也在每个插件目录中。我是不是用错了方法?
此外,我是否需要在每个插件子目录中保留包含 IBaseComponent 的 DLL 副本以及程序本身使用的副本,或者我是否做了一些不正确的事情可以让我删除此要求?
我知道我想使用 MEF,但不幸的是,因为我需要在 .net 2.0 上支持它,所以我无法使用 MEF。
最佳答案
这是 LoadLibrary() 失败。在我看来,您的插件依赖于某些非托管 DLL。是的,Windows 将很难找到这些 DLL,它没有理由查看插件目录。也许它第一次工作是因为您的应用程序的默认目录恰好设置为正确的目录。这也是解决方法,使用 Environment.CurrentDirectory。
准确找出哪些依赖项找不到是关键。非托管的不会出现在 fuslogvw.exe 中,您可以从 SysInternals 的 ProcMon 实用程序中挖掘出它。
关于c# - DLL的动态加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5123170/