MEF初体验
.net4.0发布很久了,也早就知道包含了一个叫做MEF的库,但是一直没有亲自试试看,还是有点惭愧的。这两天有些空闲,参考了MSDN和一些博客,简单体验了一下MEF。下面记录了一些要点,作为一段学习笔记吧。
MEF的全称是Managed Extensibility Framework,顾名思义MEF主要是用于解决程序的扩展问题的一个框架。MEF内置在.net Framework 4.0中,因此使用它通常不需要额外的什么程序集(MEF的命名空间是System.ComponentModel.Composition)。MEF本质上和Castle Windsor、Structure Map及Unity样,也是一种IOC容器,但MEF采用了基于Attribute的特性化编程模型,而没有采用基于配置的形式。因为配置文件对于一般用户可能还是过于复杂了。
MEF有两个核心的概念:导入与导出。导入是指可扩展的点,需要其他的实现来填充这个部分;导出则相反,是指扩展的具体实现,通过MEF的组合将这些实现组装的扩展点上去。导入和导出分别使用 Import 和 Export 特性来声明。
Export 特性可修饰类、字段、属性或方法,而 Import 特性可修饰字段、属性或构造函数参数。
下面是一个小示例。定义一个简单的需求,主程序通过扩展的方式加载一个翻译组件,然后使用翻译组件的翻译一些文字,并将来自翻译组件中的签名信息附加到翻译好的文本后,最后将内容输出。
1、建立一个解决方案,解决方案包括三个项目。控制台应用程序MEFTest,作为主程序;类库MEFTest.Interface,作为接口程序集;另一个类库MEFTest.Implementation作为接口的实现。MEFTest与MEFTest.Implementation均添加对MEFTest.Interface的引用及对MEF框架的引用。
2、在MEFTest.Interface中定义一个翻译器接口ITranslator。
using System; namespace MEFTest.Interface { public interface ITranslator { string Translate(string text); } }
3、MEFTest作为主程序,主要是提供主逻辑并且提供扩展点。定义一个类
using System; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; using MEFTest.Interface; namespace MEFTest { public class TranslationTest { public TranslationTest() { var catalog = new AggregateCatalog(); catalog.Catalogs.Add(new DirectoryCatalog(".")); var container = new CompositionContainer(catalog); container.ComposeParts(this); } [Import] public string Sign { get; set; } [Import] public ITranslator Translator { get; set; } } }
这个类中提供了两个导入(扩展点),Translator用来扩展翻译器,Sign用于签名。在构造方法在首先初始化了一组目录对象Catalog(目录对象采用组合模式实现,这里实例化了一个聚和目录AggregateCatalog,并且在聚和目录中添加了一个基于文件夹查找扩展组件的DirectoryCatelog。当TranslationTest类初始化时,MEF将在DirectoryCatelog设定的文件夹下查找扩展组件,本例是当前文件夹),然后用Catalog构造一个container对象,最后由container完成组合。
4、在MEFTest.Implementation中实现ITranslator接口,并且将这个实现类标记为导出,这是一个类型的导出。
using System; using System.ComponentModel.Composition; using MEFTest.Interface; namespace MEFTest.Implementation { /// <summary> /// 具体的计算算法实现 /// </summary> [Export(typeof(ITranslator))] //导出 public class Translator : ITranslator { public string Translate(string text) { //假设这里有一个非常强大的翻译算法 return "Promise more, not to be, that is just a lie."; } } }
5、在MEFTest.Implementation中添加一个Settings的类用于实现签名。将Sign字段标记为导出,这是一个字段的导出。
using System; using System.ComponentModel.Composition; namespace MEFTest.Implementation { public class Settings { [Export] public string Sign = "by MEFTestTranslator"; } }
6、最后,在main方法中添加一些代码将上面的类串联起来。
using System; namespace MEFTest { class Program { static void Main(string[] args) { TranslationTest tester = new TranslationTest(); string result = tester.Translator.Translate("承诺再多,做不到,那也只不过还是谎言。"); Console.WriteLine(result + "——" + tester.Sign); Console.ReadKey(); } } }
7、生成解决方案,记得将MEFTest.Implementation 生成的dll,拷贝到主程序所在的文件夹中。运行主程序,显示如下结果。
这个例子非常的简单,很多MEF的特性都没有利用的到,下面这些参考资料比较详细的讲述了MEF的各项特性,有兴趣可以学习一下。
参考资料
http://www.cnblogs.com/pszw/category/335788.html —— 我学MEF系列
http://www.cnblogs.com/beniao/archive/2010/08/11/1797537.html —— MEF程序设计指南
http://msdn.microsoft.com/zh-cn/library/dd460648 —— Managed Extensibility Framework 概述(MSDN)
http://msdn.microsoft.com/zh-cn/library/ee155691.aspx#MtViewDropDownText —— 特性化编程模型概述(MSDN)
http://msdn.microsoft.com/zh-cn/magazine/ee291628.aspx —— 在 .NET 4 中使用托管可扩展性框架构建可组合的应用程序(MSDN杂志)