技术开发 频道

MEF:.NET中值得体验的精妙设计

    【IT168 评论】    MEF(Managed Extensibility Framework)是.NET Framework 4.0一个重要的库,Visual Studio 2010 Code Editor的扩展支持也是基于MEF构建的。MEF的目标是简化创建可扩展的应用程序,其核心类是ComposablePart,即具有组合能力的组件,每一个称为ComposablePart(中文可为可组合构件,不过下文一直采用英文来表示,这样比较贴切)的组件可以组合(称为Import)其它组件的功能(其它组件通过声明Export提供功能)并且它也可以通过定义Export将其功能暴露给其它组件。ComposablePart通过组件目录(ComposablePartCatalog)来搜索发现需要的功能,组件目录可以是一个物理文件目录、网络存储等。每一个ComposablePart还具备动态组合的能力,在必要的情况下可以重新组合功能。本文将采用自底向上的思路体验一下MEF的设计思想。

  1、 无废话MEF

  MEF的核心是可组合组件ComposablePart,它由ComposablePartDefintion来描述和创建。每一个可组合组件通过定义ExportDefintion向其它组件提供功能,通过ImportDefinition引用其它组件的功能,通过Metadata来描述组件自身的信息。在创建一个ComposablePart组件后,通过在组件目录(ComposableCatalog)搜索需要的功能实现组件组合。

  2、 典型的MEF组合过程

  (1)创建组件目录(如AssemblyCatalog)

  (2)创建组合容器CompositionContainer,组件容器通过组件目录搜索组件的定义

  (3)创建一个组件

  (4)从组件容器获取其它组件功能的定义,然后执行匹配组合

  示例代码如下:

  

 

      1 var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly()); //创建一个程序集目录,用于从一个程序集获取所有的组件定义

  
2 var container = new CompositionContainer(catalog); //创建一个组合容器

  
3 var composablePart = new MyComponent();

  
4 container.ComposeParts(composablePart); //执行组合,从容器中获取ExportDefinition并创建实例组合在一起

  
5 // composablePart组合完成以供使用


  其原理如下图(来自mef.codeplex.com官方网站):

MEF_Diagram.png

           

  3 MEF本质——组合基元

  组合基元是对提供具有可扩展、可组合能力的组件的“本质”支持,它处于MEF的最底层,是整个Framework的核心类,由6个类构成,如下图所示(该图来自MEF白皮书,白皮书有点抽象,不过看起来很过瘾,后面附上本人翻译的中文版)。

image

  组合基元类的描述如下:

  (1)ComposablePart:即可组合组件,是组合基元的核心类。ExportDefinitions表示该组件提供的功能的描述;而ImportDefinitions则是对引用其它组件功能的约束的描述。Metadata是对组件自身的特殊标识,当一个ComposablePart通过Import引用其它组件功能时,元数据可能作为满足引用功能的约束的一个条件。

  (2)ExportDefinition:定义ComposablePart向其它组件提供的功能,这个功能使用一个ContactName和Metadata来描述。ContactName即使用这个功能的契约,Metadata用于进一步描述这个功能。

  (3)ImportDefinition:定义ComposablePart对其它组件提供的功能的引用,即引用了另一个组件的Exports。ImportDefintion使用一个表达式来描述约束,它在Constraint这个属性定义,其类型为Expression>。这个表达式用于对一个ExportDefintion做匹配判定,其匹配方法如下:

  var allExportDefs = …// 从ComposablePartCatalog获取所有ExportDefinition

  var constraintDelegate= Constraint.Compile(); //编译成匹配函数的代理

  var satisfiedExportDefs = allExportDefs .FindAll(constraintDelegate); //使用匹配函数的代理来过滤所有的ExportDefs

  (4)ComposableDefinition:即ComposablePart定义,是ComposablePart的工厂,该类定义了一类ComposablePart引用的功能、暴露的功能及其自身的元数据。引用的功能在ImportDefinitions中描述,暴露的功能通过ExportDefinitions描述。而Metadata则是对组件自身的描述,在MEF中一般用于在一个组件引用(Import)另一个组件功能时,通过对另一个组件的元数据进行匹配,从而来确定是否要组合另一个组件提供的功能。该类是ComposablePart的工厂,提供了CreatePart方法。

  (5)ComposablePartCatalog:可组合组件目录,用于发现组件,这些组件可能来自物理目录、网络存储等。

0
相关文章