为什么插件主机看不到我的MEF部分



我有一个小类,它从客户端执行数据导入。每个客户端都有自己版本的此类,因此它是一个MEF插件:

[Export(typeof(IXTImportEmployeePrePlugin))]
public class PreEmployeeImport : XTImportEmployeePrePlugin

然而,当我尝试导入插件时,就像这样:

var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + PluginDir);

生成的目录有1个文件和0个零件,但该零件在文件中。我已经和dotPeek核实过了。

是什么原因导致主机看不到导出的零件?我编写的另一个小型测试主机也导入了插件程序集,它认为这个部分很好。

这可能是因为未加载程序集。

我将描述调用DirectoryCatalog的构造函数后发生的过程

var catalog = new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory + "second");

调用内部方法Initialize,它基本上做两件事。它枚举*.dll文件,然后对所有文件调用Assembly.Load
Initialize完成后,集合LoadedFilesParts有望填充。

属性LoadedFiles错误地指导了调试工作,因为在该集合中有一个文件并不意味着程序集确实已加载,它只是"告诉"在该文件夹中找到一个或多个名为"*.dll"的文件。因此,LoadedFiles最好被认为是FoundFiles

在收集CCD_ 10之后,进行假定组件的实际加载。每个找到的文件都被馈送到CCD_ 11中。无论何时失败,您都将在Parts集合中没有类型。

我通过一个x86控制台应用程序试图加载一个具有我的Export类型的x64 dll来重现您的情况。由于这些都是简单的融合问题,我使用了融合日志查看器进行诊断。我的场景显示了以下错误:

操作失败。绑定结果:hr=0x800700b。尝试用于加载格式不正确的程序。

在文档中,给出了未加载组件的3个主要原因:

  • 零件在EXE文件中。默认的DirectoryCatalog只从DLL文件中读取。您可以通过使用适当的搜索模式创建DirectoryCatalog来读取其他文件
  • 零件的部件缺少引用。使用的程序集必须能够从搜索路径加载其引用,通常是从其自己的目录或全局程序集缓存加载
  • 零件的部件针对不同的CPU类型。MEF不会加载针对错误CPU类型的程序集

不知道主机应用程序/appdomain的外观,您可能需要这篇描述如何诊断融合问题的文章。它适用于框架的v2,但有些可能仍然相关。以下段落摘录自该文章:

对于BadImageFormatException:
请尝试在文件上运行peverify.exe。

对于SecurityException:
加载任何程序集都需要执行权限。

对于FileLoadException:

  • 对于"访问被拒绝"消息(对于hresult E_ACCESSDENIED,0x80070005):
    对文件运行tlist-m,查看另一个进程是否锁定了文件并且没有共享读取访问权限。

  • 对于"名为[yourAssembly]的已定位程序集的清单定义与程序集引用不匹配"消息(对于hresult FUSION_E_REF_DEF_MISMATCH,0x80131040):
    FUSION日志将说明程序集引用的哪个部分与找到的部分不匹配。它将是程序集名称、区域性、公钥(或令牌)或版本(如果找到的程序集是强名称的)。

  • 对于"无法验证的映像[yourAssembly]无法运行"或"无法运行可执行文件[yourAssembly',因为它包含重定位"消息(对于hresult COR_E_FIXUPSINEXE,0x80131019):
    该映像必须作为进程exe运行,否则将编译为dll。这是因为MC++在您的图像中为您进行了优化,假设它将是进程exe。

最新更新