MEF框架
MEF是做什么的?在MEF诞生前,人们已经开发了许多依赖注入框架来解决应用的扩展性问题,比如 EJB、CORBA、Eclipse 的OSGI 实现以及 Java 的 Spring 等等。在 Microsoft 的平台上,.NET Framework 自身内部包含组件模型和 System.Addin,此外还有不少开源解决方案,包括SharpDevelop 的SODA 体系结构和“控制反转”容器(如C
·
MEF是做什么的? 在MEF诞生前,人们已经开发了许多依赖注入框架来解决应用的扩展性问题,比如 EJB、CORBA、Eclipse 的OSGI 实现以及 Java 的 Spring 等等。在 Microsoft 的平台上,.NET Framework 自身内部包含组件模型和 System.Addin,此外还有不少开源解决方案,包括SharpDevelop 的SODA 体系结构和“控制反转”容器(如Castle Windsor、Structure Map、Spring.Net 以及Unity)。如果想了解其他方案,可以参考: 在Microsoft看来,这些方案有些过于庞杂(比如OSGI),有些则需要开发人员完成许多额外配置工作(比如Spring),MEF试图秉承这些解决方案的优点,尝试解决刚才所提及的令人头痛的问题。MEF有两个优点:第一,MEF是开源项目,其源代码在Codeplex上可以下载,第二,MEF是第一个随CLR发布的扩展性管理的框架,而且在Visual Studio和Silverlight中被广泛应用。 官方给MEF下的定义: Managed Extensibility Framework(MEF)是.NET平台下的一个扩展性管理框架,它是一系列特性的集合,包括依赖注入(DI)以及Duck Typing等。MEF为开发人员提供了一个工具,让我们可以轻松的对应用程序进行扩展并且对已有的代码产生最小的影响,开发人员在开发过程中根据功能要求定义一些扩展点,之后就可以使用这些扩展点与应用程序交互;同时MEF让应用程序与扩展程序之间不产生直接的依赖,这样也允许在多个具有相同的扩展需求之间共享扩展程序。 概念 简短说一下MEF的工作原理,MEF的核心包括一个catalog(目录)和一个CompositionContainer(组合容器)。catalog用于发现扩展,而container用于协调创建和梳理依赖性。MEF 组合模型的核心是组合容器,该容器包含所有可用的部件并执行组合操作(即,将导入和导出配对)。 这里有几个基本核心概念: 组合 Composition将几个带有不同功能的对象组合为一个或多个复杂对象的过程。组合不是从父类中继承功能,而是将几个不同的对象组合为一个对象。例如,Wing、Propeller、Fuselage 和 VerticalStablizer 对象可以组成 Aircraft 对象的一部分。 可组合的部件 Parts 是 MEF 的关键构建块。ComposableParts 支持应用程序通过 Exports 和 Imports 公开和使用组件扩展。 一个部件向其他部件提供服务,或使用其他部件提供的服务。MEF 中的部件可来自任何位置(应用程序内部或外部);从 MEF 的角度来看,这并无区别。 导出Export — 导出是部件提供的服务。某个部件提供一个导出时,称为该部件导出 该服务。 导入Import — 导入是部件使用的服务。某个部件使用一个导入时,称为该部件导入 该服务。 契约 — 契约是Export和 Import 组件之间的通信途径。导出程序指定其提供的字符串约定,导入程序指定其需要的约定。MEF可以从要导出和导入的类型派生约定名称,因此在大多数情况下,您不必考虑这一点。 MEF入门:寻找变化点 MEF是怎样工作的呢?我们来看最简单的“Hello,World”: static void Main(string[] args) { Console.WriteLine("Hello,World."); } 根据某些业务要求,该字符串将来可能发生变化,也就是说这里有可能是一个变化点,也是一个扩展点,那我们现在使用MEF对其进行重新设计,我们将会把这个过程分成两个部分,一部分用于提供字符串: public class StringProvider { [Export("Message")] public String Output { get { return "Hello,World"; } } } 我们为Output属性添加了一个Export特性,这标识着此处有一个输出,它使的MEF能够对其进行识别。 我们再定义一个输入,即用来消费该字符串,同样是一个简单的属性,不过这次添加的是Import特性: public class Client { [Import("Message")] private String message=null; public void print() { Console.WriteLine(this.message); } } 这样就完成了导入导出的接口与实现的开发及特性配置。就剩下一步组合了: using System; using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting; namespace cc.ejb.blogs.example { class Program { static void Main(string[] args) { CompositionContainer container = new CompositionContainer(); CompositionBatch batch = new CompositionBatch(); Client client = new Client(); batch.AddPart(new StringProvider()); batch.AddPart(client); container.Compose(batch); client.print(); } } } 这里我们创建了一个组合容器对象(CompositionContainer)的实例,然后将需要组合的部件(Parts)添加到容器中即可。 多种组合方式 实际应用中,通常会定义许多导入(Import)和导出(Export)部件,这里MEF提供了不同的组合方式, 可以通过程序集(AssemblyCatalog)或目录(DirectoryCatalog) 或二者结合等方式绑定可扩展的对象。 你可以通过程序集: CompositionContainer container = new CompositionContainer(new AssemblyCatalog(typeof(Client).Assembly)); Client client = new Client(); container.SatisfyImportsOnce(client); client.print(); 也可以使用DirectoryCatalog,则在该目标路径下的所有程序集都会被遍历查询: CompositionContainer container = new CompositionContainer(new DirectoryCatalog(System.IO.Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location),"*.exe")); Client client = new Client(); container.SatisfyImportsOnce(client); client.print(); 注意: DirectoryCatalog默认的SearchPattern是”*.dll”,由于我们只有一个可执行的assmebly,所以应该改成”*.exe”,这样才会被正确加载。 当然也可以二者相结合: AggregateCatalog catalog = new AggregateCatalog(); catalog.Catalogs.Add(new AssemblyCatalog(typeof(Client).Assembly)); CompositionContainer _container = new CompositionContainer(catalog); … 参考: MSDN有关文章 http://hi.baidu.com/oeezee/blog/item/346a7afb9299ded1b58f3131.html
更多推荐
已为社区贡献2条内容
所有评论(0)