MEF学习系列(4): 组合容器(CompositionContainer)和目录(Catalog)
2013-08-22 15:26
253 查看
前言
通过之前的文章,我们已经了解了MEF中的导入(Import)和导出(Export)。在本系列的第一篇文章中我们知道MEF其实还包括另外两个核心内容:组合容器(CompositionContainer)和目录(Catalog)。组合容器
Castle有容器,Unity有容器,同样作为一个能够提供扩展机制,能够支持依赖注入的框架肯定也有容器。MEF的组合模型的核心是组合容器,该容器包含所有的部件并执行组合操作(即,将导入和导出配对)。通常我们使用的组合容器是:CompositionContainer,MEF还提供了一个组合对象:CompositionBatch。可以理解组合容器“加工工厂”。目录
前面我们有谈到组合容器中包含的所有可用部件,并对这些组件执行组合操作,我们可能会问容器怎么发现这些部件呢?答案就是:目录(Catalog)。目录就是一个对象,通过它可从某些源发现可用部件。MEF提供了用于从提供的类型、程序集和目录发现部件的目录。应用程序开发人员可以轻松地创建用于从其他源(例如Web服务)发现部件的新目录。
MEF中提供的目录对象主要有:Assembly Catalog(程序集目录);Directory Catalog;Aggregate Catalog;Type Catalog和仅使用在Silverlight中的目录Deployment Catalog(Silverlight Only);Filtered Catalog。
1. Assembly Catalog
可以在给定的Assembly程序集中发现所有的导出部件,使用类型AssemblyCatalog。//指定目录为当前执行的程序集 var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
2. Directory Catalog
它可以在给定的目录(路径,相对路径或绝对路径)中发现导出部件,使用类型DirectoryCatalog。如果你使用的是相对路径,则相对的是当前AppDomain的基路径。DirectoryCatalog支队对给定目录进行一次性扫描,目录发生变化是容器不会主动刷新,如果需要刷新给定的目录需要调用方法:Refresh(),当目录刷新时,容器也会重新组合部件。var catalog = new DirectoryCatalog("Extensions"); catalog.Refresh();
3. Aggregate Catalog
聚集目录,有时候我们使用单一的AssemblyCatalog和DirectoryCatalog并不能解决我们的需求,我们可能需要同时使用到他们,这个时候我们便可以使用Aggregate Catalog,我们可以将Assembly Catalog和Directory Catalog同时添加到目录中,这种添加可以通过构造函数实现,也可以通过目录集合的添加方法来实现:catalog.Catalogs.Add(...)。聚集目录使用类型AggregateCatalog。var catalog = new AggregateCatalog( new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()), new DirectoryCatalog("Extensions") );
4. Type Catalog
通过Type Catalog我们可以发现指定类型中的导出部件。使用类型TypeCatalogvar catalog = new TypeCatalog(typeof(type1),typeof(type2),...);
5. Deployment Catalog
Deployment Catalog,这种类型的目录仅支持Silverlight,在后面的文章中我们会专门讲到如何在Silverlight中使用MEF。6. Filtered Catalog
已过滤的目录,通过FilteredCatalog可以筛选出特定的目录,特别是,可以请求所有可加载的插件都有一个知识级别的元数据属性。var catalog = new AssemblyCatalog(typeof(Program).Assembly); var parent = new CompositionContainer(catalog); var filteredCat = new FilteredCatalog(catalog, def => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) && ((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) == CreationPolicy.NonShared); var child = new CompositionContainer(filteredCat, parent); var root = child.GetExportedObject<Root>(); child.Dispose();
一个简单的例子
简单完整的一个例子,该DEMO是一个控制台程序,运行结果会打印出一行字符串:1. 要先定义一个接口,用于指定导入导出使用。
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace MEFDemo1 { //第一步:先定义一个接口,用于指定类型使用。定义日志接口 public interface ILog { void AddLog(Exception ex); } }
2. 定义Export导出部件
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition; namespace MEFDemo1 { //第二部:设置导出部件,并且导出部件的类要继承与第一步的接口类。 //并且导出部件的类型为接口类型 //导出部件,指定协议类型为(ContractType)为ILog [Export(typeof(ILog))] public class MyLog:ILog { public void AddLog(Exception ex) { Console.WriteLine(ex.ToString()); } } }
3. 在主程序里进行组合并使用
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace MEFDemo1 { class Program { //第三部:导入部件到执行类中的属性中,并且属性的类型为第一步定义的接口类型。 //把导出的服务部件导入到属性Log里,使用默认的ContractType和ContractName [Import] public ILog Log { set; get; } static void Main(string[] args) { Program pro = new Program(); pro.Compose(); //第五步:组合完成后,就可以调用当前类对象的导入部件属性的导出部件的方法MainClassObject.ImportProperty.ExportClassFunction //使用当前对象Log属性的AddLog方法,由于Log属性已经由MyLog导入成功, //所以这里调用的AddLog方法就是MyLog类的AddLog方法。 pro.Log.AddLog(new Exception("My First MEF")); Console.Read(); } //第四部:组合导出部件到导入部件中。 //组合方法 private void Compose() { //指定目录为当前执行的程序集 var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()); //使用AssemblyCatalog创建组合容器 var container = new CompositionContainer(catalog); //调用组合部件方法 container.ComposeParts(this); } } }
源代码: http://download.csdn.net/detail/eric_k1m/5993465
相关文章推荐
- 我学MEF系列(4):组合容器(CompositionContainer)和目录(Catalog)
- MEF应用(4) 组合容器 目录
- [C++再学习系列] STL容器删除操作总结
- MEF学习系列笔记系列(1)
- MEF学习系列笔记系列(1)
- [C++再学习系列] STL容器删除操作总结
- Entity Framework Code First学习系列目录
- [C++再学习系列] STL容器删除操作总结
- STL学习系列九:Map和multimap容器
- PX4代码学习系列博客(3)——px4固件目录结构和代码风格
- STL学习系列二:Vector容器
- Linux 系统化学习系列文章总目录(持续更新中)
- 【Spring源码深度解析学习系列】容器的基础XmlBeanFactory(二)
- 博客整理:Oracle 表系列学习目录
- [MEF]第05篇 MEF的目录(Catalog)筛选
- STL泛型编程学习之String系列容器
- C++ 学习系列之 容器(一)map
- ABP入门系列目录——学习Abp框架之实操演练
- 网易云课堂Java进阶学习笔记系列01 -- 第3周 对象容器
- MEF学习系列笔记系列(1)