此章节来自msdn。

一、一般调试方法

在 Managed Extensibility Framework (MEF) 中调试问题可能非常困难,因为潜在问题与标准应用程序中的潜在问题不同。 本主题提供了特定于 MEF 的问题诊断技巧,并且提供了这些问题的一些可能原因。

发现 MEF 问题

解决 MEF 问题的第一步是在应用程序的 MEF 部分中定位问题。 下表列出了特定于 MEF 的问题。

问题

可能的原因

组合期间引发 ImportCardinalityMismatchException 异常。

由于部件缺失或被拒绝,无法使用匹配的导出填充导入。

- 或 -

预期单个导出的导入发现多个匹配项。

具有 ImportManyAttribute 特性的集合缺少预期内容。

预期部件缺失或被拒绝。

DefaultValueAttribute 特性设置为 true 的导入意外未填充。

预期的匹配项缺失或被拒绝。

处理异常和 DisableSilentRejection


MEF 旨在可靠地适应各种配置。 默认情况下,它忽略具有缺少必需的依赖项的部分。 但是,当您调试应用程序时,这种可靠性会使查找问题原因更困难。 您可以采用这些步骤更轻松地跟踪问题:

引发异常时,请配置 Visual Studio 调试器中断。

配置您的 CompositionContainer 对象禁用拒绝。

通常,如果应用程序引发异常,则 Visual Studio 调试器将中断执行仅当该异常不随后处理。 但是,您可能会发现,当引发异常时,立即停止并调试您的 MEF 应用程序会很有帮助,因为您的应用程序会以某些方式处理异常,而不会将其体现在调试器中。 若要在引发异常时配置 Visual Studio 调试器,在菜单栏上,选择调试异常。 确保选择了所有异常的引发框,您想要将调试器设置为遇到这些异常时中断。 (有关 MEF,这些是在 System.ComponentModel.Composition 下的异常。这些异常此时将显示在调试器中,即使您的应用程序处理了这些异常。

默认情况下,MEF 使用叫做拒绝的处理确定将用于实例化调用哪些部件具有相关性。 组合引擎检查新部件的添加是否将导致组合失败。 如果它们可能会导致失败,则从容器中隐藏那些部件,但不引发异常。 在面对部署配置时此行为会使应用程序更稳定,但可能使调试更难。 若要每当部件被拒绝时关闭拒绝,并确保 MEF 引发异常,将 DisableSilentRejection 值设置传递到 CompositionContainer 或 ExportProvider 对象。 以下代码对此进行了说明:

代码段

var catalog = new DirectoryCatalog("Extensions");
var container = new CompositionContainer(catalog, CompositionOptions.DisableSilentRejection);

MEF 失败通常是级联的,即组合一个部件失败会导致组合第二个部件失败以此类推,直到观测到的失败点在异常的长列表中丢失。 为帮助诊断此属性的问题,CompositionException 异常提供 RootCauses 属性。 您可以检查在调试器中的此属性以查找是组合中每个错误的根本原因的异常。

跟踪


从开始 .NET Framework 4.5,MEF 支持跟踪。 运行时,以 Visual Studio 的调试模式,组合故障和异常将写入“IntelliTrace”窗口。 检查这些结果有助于诊断组合失败。 有关使用 IntelliTrace 的更多信息。

检查可用部件


若要确定哪些部件可用于目录,可以在调试器中检查目录的 Parts 属性,在代码中循环访问该属性。

如果希望看到的部件不存在,则表示未发现或者已拒绝这些部件。

如果可以看到一个部件,但是它与您希望它填充的导入不匹配,则表示出现了某种类型的不匹配。

导出/导入不匹配


为了使导出与特定导入匹配,必须满足以下所有条件。 如果未出现预期匹配,但是您已确认导出存在于目录中,请仔细检查这些条件。 手动构造协定以匹配特定导出时,这些条件也适用。

属性

匹配的条件

协定名称

必须完全匹配并且区分大小写。 如果协定名称是从类型推断得出的(例如,在没有任何参数的情况下应用 ExportAttribute 特性时),则唯一可能的匹配项是从同一类型推断得出的另一名称。

协定类型

必须完全匹配。 不支持多态匹配。 即使提供了匹配的协定名称,协定类型也必须匹配。

必需的元数据

导入通过其元数据视图的属性要求的所有元数据必须由导出通过 ExportMetadataAttribute 特性或自定义元数据特性提供。 元数据键(元数据视图中属性的名称)和元数据值的类型必须匹配。

创建策略

导出和导入不能指定不同的创建策略。 有关更多信息,请参见 CreationPolicy。

发现问题


如果部件未显示在目录中或者使用组合分析工具 (Mefx) 时未显示,则表示目录未发现该部件。 这里是导致此故障的一些可能原因:

该部件是抽象‏‎‏‏‏‏‎‎类型。 抽象类型不能用作部件。 使类型成为非抽象类型,或者创建非抽象子类型。

ImportingConstructorAttribute 特性缺失。 对于具有多个构造函数或者仅具有接受参数的构造函数的部件,必须指定一个构造函数,以便 MEF 使用 ImportingConstructorAttribute 特性。

该部件具有 PartNotDiscoverableAttribute 特性。 此特性阻止部件被发现。

该部件是开放式泛型类型。 MEF 不支持开放泛型。 请使用类型的封闭式子类,或者导出单个属性。

您使用 DirectoryCatalog 对象时可能出现其他故障:

该部件位于 .exe 文件中。 默认 DirectoryCatalog 仅从 DLL 文件读取。 通过使用相应搜索模式创建,可以使用 DirectoryCatalog 对象从其他文件读取。

部件的程序集具有缺失的引用。 使用的程序集不能从搜索路径(通常从它们自己的目录或者从全局程序集缓存)加载其引用。

该部件的程序集面向其他 CPU 类型。 MEF 不会加载面向错误 CPU 类型的程序集。

二、组合分析工具(Mefx)

组合分析工具 (Mefx) 是分析包含 Managed Extensibility Framework (MEF) 部件的库 (.dll) 和应用程序 (.exe) 文件的命令行应用程序。 Mefx 的主要目的是向开发人员提供一种方式,以允许他们无需向应用程序本身添加繁琐的跟踪代码即可诊断 MEF 应用程序中的组合故障。 它还可用于帮助了解第三方提供的库中的部件。 本主题描述如何使用 Mefx 并且提供了语法参考。

本主题包括下列各节。

获取 Mefx


可在 Codeplex 的 Managed Extensibility Framework 上获取 Mefx。 下载和解压缩该工具即可。

基本语法


Mefx 从命令行使用以下格式调用:

mefx [files and directories] [action] [options]

第一组参数指定从中加载部件进行分析的文件和目录。 使用 /file: 开关指定文件,使用 /directory: 开关指定目录。 可以指定多个文件或目录,如下面的示例所示:

mefx /file:MyAddIn.dll /directory:Program\AddIns [action...]

说明

每个 .dll 或 .exe 应仅加载一次。 如果多次加载一个文件,该工具可能会返回不正确的信息。

在文件和目录列表后面,必须指定命令以及该命令的任何选项。

列出可用部件


使用 /parts 操作可列出在加载的文件中声明的所有部件。 结果为简单的部件名称列表。

mefx /file:MyAddIn.dll /parts

MyAddIn.AddIn

MyAddIn.MemberPart

若要获取有关部件的更多信息,请使用 /verbose 选项。 这将输出所有可用部件的更多信息。 若要获取有关单个部件的更多信息,请使用 /type 操作而不是 /parts。

mefx /file:MyAddIn.dll /type:MyAddIn.AddIn /verbose

[Part] MyAddIn.MemberPart from: AssemblyCatalog (Assembly=" MyAddIn, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Export] MyAddIn.MemberPart (ContractName=" MyAddIn.MemberPart")

列出导入和导出


/imports 和 /exports 操作将分别列出所有导入的部件和所有导出的部件。 还可以使用 /importers 或 /exporters 操作列出导入或导出特定类型的部件。

mefx /file:MyAddIn.dll /importers:MyAddin.MemberPart

MyAddin.AddIn

还可以对这些操作应用 /verbose 选项。

查找拒绝的部件


加载可用的部件后,Mefx 使用 MEF 组合引擎组合它们。 不能成功组合的部件称为“拒绝的部件”。 若要列出所有拒绝的部件,请使用 /rejected 操作。

可以将 /verbose 选项与 /rejected 操作结合使用,以输出有关拒绝的部件的详细信息。 在下面的示例中,ClassLibrary1 DLL 包含 AddIn 部件,它导入 MemberPart 和 ChainOne 部件。 ChainOne 导入 ChainTwo,但是 ChainTwo 不存在。 这意味着 ChainOne 被拒绝,这将导致 AddIn 被拒绝。

mefx /file:ClassLibrary1.dll /rejected /verbose

下面显示了前面的命令的完整输出:

[Part] ClassLibrary1.AddIn from: AssemblyCatalog (Assembly="ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Export] ClassLibrary1.AddIn (ContractName="ClassLibrary1.AddIn")

[Import] ClassLibrary1.AddIn.memberPart (ContractName="ClassLibrary1.MemberPart")

[SatisfiedBy] ClassLibrary1.MemberPart (ContractName="ClassLibrary1.MemberPart") from: ClassLibrary1.MemberPart from: AssemblyCatalog (Assembly="ClassLibrar

y1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Import] ClassLibrary1.AddIn.chain (ContractName="ClassLibrary1.ChainOne")

[Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No valid exports were found that match the constraint '((exportDefinition.ContractName == "ClassLibrary1.ChainOne") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "ClassLibrary1.ChainOne".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.

at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)

at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id)

[Unsuitable] ClassLibrary1.ChainOne (ContractName="ClassLibrary1.ChainOne")

from: ClassLibrary1.ChainOne from: AssemblyCatalog (Assembly="ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Because] PartDefinitionIsRejected, The part providing the export is rejected because of other issues.

[Part] ClassLibrary1.ChainOne from: AssemblyCatalog (Assembly="ClassLibrary1, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null")

[Primary Rejection]

[Export] ClassLibrary1.ChainOne (ContractName="ClassLibrary1.ChainOne")

[Import] ClassLibrary1.ChainOne.chain (ContractName="ClassLibrary1.ChainTwo")

[Exception] System.ComponentModel.Composition.ImportCardinalityMismatchException: No valid exports were found that match the constraint '((exportDefinition.ContractName == "ClassLibrary1.ChainTwo") AndAlso (exportDefinition.Metadata.ContainsKey("ExportTypeIdentity") AndAlso "ClassLibrary1.ChainTwo".Equals(exportDefinition.Metadata.get_Item("ExportTypeIdentity"))))', invalid exports may have been rejected.

at System.ComponentModel.Composition.Hosting.ExportProvider.GetExports(ImportDefinition definition, AtomicComposition atomicComposition)

at Microsoft.ComponentModel.Composition.Diagnostics.CompositionInfo.AnalyzeImportDefinition(ExportProvider host, IEnumerable`1 availableParts, ImportDefinition id)

需要关注的信息包含在 [Exception] 和 [Unsuitable] 结果中。 [Exception] 结果提供有关部件为什么被拒绝的信息。 [Unsuitable] 结果指明以其他方式匹配的部件为什么无法用于填充导入;在本例中,因为该部件本身因缺失导入被拒绝。

分析主要原因


如果一些部件链接在较长的依赖关系链中,则问题涉及的部件靠近底部时可能会导致整个链被拒绝。 诊断这些问题可能非常困难,因为故障的根本原因并不总是非常明显。 为了帮助诊断问题,可以使用 /causes 操作,它尝试查找所有级联拒绝的根本原因。

对前面的示例使用 /causes 操作仅列出 ChainOne 的信息,它未填充导入是拒绝 AddIn 的根本原因。 /causes 操作可以在正常和 /verbose 选项中使用。

说明

在大多数情况下,Mefx 能够诊断出级联故障的根本原因。 然而,对于部件以编程方式添加到容器的情况、涉及分层容器的情况或者涉及自定义 ExportProvider 实现的情况,Mefx 将无法诊断出原因。 通常,应尽可能避免前面所述的情况,因为故障通常很难诊断。

白名单


/whitelist 选项允许您指定一个文本文件,其中列出应该被拒绝的部件。 然后,将标记意外拒绝。 分析不完整的库或者缺少一些依赖项的子库时,这可能非常有用。 /whitelist 选项可应用于 /rejected 或 /causes 操作。

请考虑一个名为 test.txt 的文件,它包含文本“ClassLibrary1.ChainOne”。 如果对前面的示例运行带有 /whitelist 选项的 /rejected 操作,则将生成以下输出:

mefx /file:ClassLibrary1.dll /rejected /whitelist:test.txt

[Unexpected] ClassLibrary1.AddIn

ClassLibrary1.ChainOne

MEF 调试的更多相关文章

  1. MEF依赖注入调试小技巧!

    自从哥的项目使用MEF以来,天天那个纠结啊,甭提了.稍有错误,MEF就报错,但就不告诉你哪错了,大爷的. 后来看了MEFX的相关调试方法,感觉也不太理想,根本不够直观的看到错误原因,也许是没有深入学习 ...

  2. 实战MEF(1):一种不错的扩展方式

    在过去,我们完成一套应用程序后,如果后面对其功能进行了扩展或修整,往往需要重新编译代码生成新的应用程序,然后再覆盖原来的程序.这样的扩展方式对于较小的或者不经常扩展和更新的应用程序来说是可以接受的,而 ...

  3. C#进阶系列——MEF实现设计上的“松耦合”(一)

    前言:最近去了趟外地出差,介绍推广小组开发的框架类产品.推广对象是本部门在项目上面的同事——1到2年工作经验的初级程序员.在给他们介绍框架时发现很多框架设计层面的知识他们都没有接触过,甚至没听说过,这 ...

  4. C#进阶系列——MEF实现设计上的“松耦合”(四):构造函数注入

    前言:今天十一长假的第一天,本因出去走走,奈何博主最大的乐趣是假期坐在电脑前看各处堵车,顺便写写博客,有点收获也是好的.关于MEF的知识,之前已经分享过三篇,为什么有今天这篇?是因为昨天分享领域服务的 ...

  5. Prism 5 + MEF中的ModuleCatalog.CreateFromXaml问题

    protected override IModuleCatalog CreateModuleCatalog() { return Microsoft.Practices.Prism.Modularit ...

  6. MEF核心笔记(6)让 MEF 拥抱 AOP

    场景: 最近推荐同事在项目中使用起了 MEF,用其构建一个插件式的多人开发框架,因为该框架不是让我去设计了,所以对于 MEF 和 IOC 等概念不是很了解的同事,便会出现各种问题.接入 AOP 便是其 ...

  7. VS 本机调试

    VS~通过IIS网站启用"域名"调试 在我们开发网站时,对某些信息进行序列化时,通常使用session,cookies,nosql等技术,而为了安全,我们在服务器上很多情况都做了防 ...

  8. 一周一话题之一(EF-CodeFirst、MEF、T4框架搭建学习)

    本话题是根据郭明峰博客<MVC实用架构系列>的搭建学习总结. -->目录导航 一.数据仓储访问的构建     1.UnitOfWork的构建     2.Repository的构建 ...

  9. MEF 插件式开发之 DotNetCore 初体验

    背景叙述 在传统的基于 .Net Framework 框架下进行的 MEF 开发,大多是使用 MEF 1,对应的命名空间是 System.ComponentModel.Composition.在 Do ...

随机推荐

  1. WinForm中 事件 委托 多线程的应用

    WinForm中 事件 委托 多线程的应用[以一个下载进度条为例] 第一步:首先我们创建一个winfor的项目 第二步:我们建一个窗体在一个窗体里面 打开一个另外的窗体 另外的窗体有一个按钮 点击后就 ...

  2. JavaEE:Cookie和Session

    Cookie是客户端技术,程序把每个用户的数据以cookie的形式写给用户各自的浏览器.当用户使用浏览器再去访问服务器中的web资源时,就会带着各自的数据去.这样web资源处理的就是用户各自的数据了. ...

  3. rabbitmq在mac上安装

    1.安装brew 打开http://bash.sh  执行 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/ ...

  4. 设计模式:空对象模式(Null Object Pattern)

    设计模式:空对象模式(Null Object Pattern) 背景 群里聊到<ASP.NET设计模式>,这本书里有一个“Null Object Pattern”,大家就闲聊了一下这个模式 ...

  5. JS,CSS是前端,JAVA PHP ASP是后端,数据库是后端的处理对象,非代表前后底

    大海-mysql-oracle(529513481)  19:02:18 象我这边,前台都是php,而php做数据分析是不太理想的,做中间件没人力,难办 横瓜(601069289) 19:20:15  ...

  6. 利用jquery对ajax操作,详解原理(附代码)

    1. jQuery load() 方法 jQuery load() 方法是简单但强大的 AJAX 方法. load() 方法从服务器加载数据,并把返回的数据放入被选元素中. 语法: $(selecto ...

  7. gearman的安装和配置

    gearman作为并发任务管理服务,已经越来越多攻城狮在生产环境中使用了.为了日后方便部署到服务器,我写了一个shell. 一般服务器使用稳定的centos,我使用的是centos6.7. 安装she ...

  8. Android插件简介

    /** * @actor Steffen.D * @time 2015.02.06 * @blog http://www.cnblogs.com/steffen */ Android插件简介 Andr ...

  9. In-Memory:内存优化数据的持久化和还原

    数据持久化是还原的前提,没有数据的持久化,就无法还原内存优化表的数据,SQL Server In-Memory OLTP的内存数据能够持久化存储,这意味着内存数据能够在SQL Server实例重启之后 ...

  10. 利刃 MVVMLight 2:Model、View、ViewModel结构以及全局视图模型注入器的说明

         上一篇我们已经介绍了如何使用NuGet把MVVMLight应用到我们的WPF项目中.这篇我们来了解下一个基本的MVVMLight框架所必须的结构和运行模式. MVVMLight安装之后,我们 ...