MEF入门.docx_第1页
MEF入门.docx_第2页
MEF入门.docx_第3页
MEF入门.docx_第4页
MEF入门.docx_第5页
已阅读5页,还剩49页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

MEF入门目录概述3解决的问题3工作原理4从这里开始5更上一层楼15参考资源19概述MEF全称Managed Extensibility Framework(受管理扩展性框架),是微软.NET框架下为提高应用和组件复用程度而推出的。使用MEF能够使静态编译的.NET应用程序转换为动态组合,这将是创建可扩展应用、可扩展框架和应用扩展的好途径。它将做为.NET Framework 4.0的组成部分之一发布。现在,这个框架在.NET3.5中也可以运行。解决的问题MEF解决了什么呢?以往,如果一个应用程序需要支持插件方式必须要实现自己的底层并且这些插件通常是针对特有应用的,不能被其他应用所使用。实际上MEF提供了发现和组合的能力使你的应用程序可以加载扩展,为运行时的可扩展性提供了一种简单的解决方法:MEF为宿主应用提供了一种标准的途径来暴露自身并使用外部扩展。而扩展本身是可以被不同的应用程序所使用的。而一个扩展依旧可以通过针对特定应用的方法来实现。扩展之间也可以存在依赖关系,MEF则会自动将它们按照正确的顺序进行调用。MEF还提供了一些用来定位和加载可用扩展的方法。MEF允许使用附加元数据对扩展进行标记,从而达到易于丰富的查询和筛选的目的。工作原理 简短说一下MEF的工作原理,MEF的核心包括一个catalog和一个CompositionContainer。category用于发现扩展,而container用于协调创建和梳理依赖性。每个可组合的Part提供了一个或多个Export,并且通常依赖于一个或多个外部提供的服务或Import。每个Part管理一个实例为应用程序运行。Export ImportPart宿主应用PartPart从这里开始下面我们从最简单的一个例子开始:Hello World!using System;namespace HelloWorld class Program static void Main(string args) Program program = new Program(); program.Run(); public void Run() Console.WriteLine(Hello World!); Console.ReadKey(); 现在,如果不希望总是打印相同的字符串,我们应该稍微重构一下,把字符串提出来:using System;namespace HelloWorld class Program public string Message get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() Console.WriteLine(Message); Console.ReadKey(); 下面来添加信息,并调用:ProgramSimpleHellousing System;namespace HelloWorld class Program public string Message get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() SimpleHello simpleHello = new SimpleHello(); Message = simpleHello.Message; Console.WriteLine(Message); Console.ReadKey(); public class SimpleHello public string Message get return Hello World!; 到这里先打住!看上面这段代码!这段代码已经出现了紧偶合!现在开始!进军MEF!首先要添加对MEF压缩包中System.ComponetModel.Composition.dll的引用。好了,现在我开始改造我们的代码,解掉偶合。ProgramSimpleHello去掉耦合!using System;using System.ComponentModel.Composition;namespace HelloWorld class Program Import public string Message get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; Console.WriteLine(Message); Console.ReadKey(); public class SimpleHello Export public string Message get return Hello World!; 现在加入调用逻辑SimpleHelloProgramusing System;using System.ComponentModel.Composition;using System.Reflection;namespace HelloWorld class Program Import public string Message get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catalog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catalog.CreateResolver(); container.AddPart(this); container.Compose(); Console.WriteLine(Message); Console.ReadKey(); public class SimpleHello Export public string Message get return Hello World!; 现在,程序可以正常运行了!注意到在这个步骤中,我们做的几件事情:i. 创建了一个catalog,它将告诉MEF到什么地方去寻找Import和Export。在这个例子中,我们告知在当前运行的程序集中。出此之外还有很多种catalog,我们稍候会看到,当然你也可以去创建自己的catalog。ii. 创建了一个CompositionContainer,这是个高效的方式使不同的part在一起被调用。iii. 将Program的实例加入到container以便调用其依赖项。iv. 施展Compose魔法!Message属性将在这步得到设置。再做些更有趣的事情,我们来再添加一个信息:using System;using System.ComponentModel.Composition;using System.Reflection;namespace HelloWorld class Program Import public string Message get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catelog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); Console.WriteLine(Message); Console.ReadKey(); public class SimpleHello Export public string Message get return Hello World!; public class MoreMessages Export public string Message get return Hello Again!; 运行!程序竟然崩掉了!从错误信息可以看到,有太多的Export与Import适合,MEF不知道应该使用哪个Export。然而,事实上很幸运,你可以告诉MEF可以处理0或多个结果,你要做的只是如下修改Message属性:using System;using System.ComponentModel.Composition;using System.Reflection;using System.Collections;using System.Collections.Generic;namespace HelloWorld class Program Import public IEnumerable Messages get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catelog = new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); foreach (var msg in Messages) Console.WriteLine(msg); Console.ReadKey(); public class SimpleHello Export public string Message get return Hello World!; public class MoreMessages Export public string Message get return Hello Again!; WOW!太棒了!现在我们把这个例子变得再复杂些。我们通常将相互没有依赖关系的组放在不同的组件中,比如在不同的应用程序集中。为了演示MEF对此支持,我们需要添加一个新建类库项目到解决方案中。同HelloWorld项目一样,我们需要将System.ComponetModel.Composition.dll添加到HelloWorldMessage项目的引用中。然后我们建立下面两个类:using System;using System.ComponentModel.Composition;namespace HelloWorldMessage public class MessageA Export public string Message get return Hello A!; using System;using System.ComponentModel.Composition;namespace HelloWorldMessage public class MessageB Export public string Message get return Hello B!; 现在,我们需要做的应该是在catalog中调用这些类,所以我们需要在目录中查找相应的part。using System;using System.ComponentModel.Composition;using System.Reflection;using System.Collections;using System.Collections.Generic;namespace HelloWorld class Program Import public IEnumerable Messages get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catelog = new DirectoryPartCatalog(.HelloWorldMessagebinDebug); / new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); foreach (var msg in Messages) Console.WriteLine(msg); Console.ReadKey(); 注意:DirectoryPartCatalog支持相对于AppDomain.CurrentDomain.BaseDirectory的相对路径中Part的查找。运行!可是我们还想要我们原来的SimpleHello和MoreMessage。很幸运我们还有一个聚合catalog来从不同的一些资源中获取 part。using System;using System.ComponentModel.Composition;using System.Reflection;using System.Collections;using System.Collections.Generic;namespace HelloWorld class Program Import public IEnumerable Messages get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catalog = new AggregatingComposablePartCatalog(); catalog.Catalogs.Add(new DirectoryPartCatalog(.HelloWorldMessagebinDebug); catalog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catalog.CreateResolver(); container.AddPart(this); container.Compose(); foreach (var msg in Messages) Console.WriteLine(msg); Console.ReadKey(); public class SimpleHello Export public string Message get return Hello World!; public class MoreMessages Export public string Message get return Hello Again!; 现在,我们只要将我们的扩展dll拷贝到指定的目录就可以实现扩展了。更上一层楼你也许看到了,主程序与Console.WriteLine()之间存在紧偶合,但有时我们并不一定需要将信息输出到Console上,有时需要记录到日志中,有时需要输出到WPF中,这时我们应该如何使用MEF对此进行处理呢?首先我们要定义一个接口来描述输出字符串的约定。为确保正确的依赖管理我们要创建一个新的类库项目”SharedLibrary”,向其中添加此接口并将其引用到其它团队项目中。using System;namespace SharedLibrary public interface IOutputString void OutputString (string value); 回过头,我们现在来讲主程序中的Console.WriteLine()去掉了! class Program Import public IEnumerable Message get; set; Import public IOutputString Out get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() /SimpleHello simpleHello = new SimpleHello(); /Message = simpleHello.Message; var catelog = new AggregatingComposablePartCatalog(); catelog.Catalogs.Add(new DirectoryPartCatalog(.HelloWorldMessagebinDebug); catelog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); foreach (var msg in Message) Out.OutputString(msg); Console.ReadKey(); 在这里我们定义了Out并用Out.OutputString()替换了Console.WriteLine()。现在,在HelloWorldMessage项目中添加下面这个类:using System;using System.Collections.Generic;using SharedLibrary;using System.ComponentModel.Composition;namespace SharedLibrary Export(typeof(IOutputString) public class OutputExt1:IOutputString public void OutputString(string value) Console.WriteLine(Output= + value); 现在生成并运行主程序!神奇吧!下面我们再来做一个IOutputString的实现,这次我们要做的更有创造力一些。using System;using System.Linq;using SharedLibrary;using System.ComponentModel.Composition;namespace SharedLibrary Export(typeof(IOutputString) public class OutputExt2 : IOutputString public void OutputString(string value) foreach (var s in value.Split().Reverse() Console.ForegroundColor = (ConsoleColor)(s.Length % 10); Console.Write(s + ); Console.WriteLine(); 和Message属性一样,我们需要MEF处理多个Export,我们应当修改一下Out属性。 class Program Import public IEnumerable Messages get; set; Import public IEnumerable OutputSet get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() var catelog = new AggregatingComposablePartCatalog(); catelog.Catalogs.Add(new DirectoryPartCatalog(.HelloWorldMessagebinDebug); catelog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); foreach (var Out in OutputSet) foreach (var msg in Messages) Out.OutputString(msg); Console.ReadKey(); 现在,主程序中的真实逻辑只剩下嵌套的 foreach循环了,我们用相同的思路将其从主程序中分离出来。我们这里使用了一个Action对foreach嵌套进行抽象和分离。 class Program Import public IEnumerable Messages get; set; Import public IEnumerable OutputSet get; set; Import(OutputMessages) public ActionIEnumerable, IEnumerable OutputMessages get; set; static void Main(string args) Program program = new Program(); program.Run(); public void Run() var catelog = new AggregatingComposablePartCatalog(); catelog.Catalogs.Add(new DirectoryPartCatalog(.HelloWorldMessagebinDebug); catelog.Catalogs.Add(new AttributedAssemblyPartCatalog(Assembly.GetExecutingAssembly(); var container = new CompositionContainer(catelog.CreateResolver(); container.AddPart(this); container.Compose(); OutputMessages(OutputSet, Messages); 现在,我们的主程序只有很松散的偶合了。下一步开始实现输出用的Action,我们。using System;using System.Collections.Generic;using SharedLibrary;using System.ComponentModel.Composition;namespace SharedLibrary public class OutputAction Export(OutputMessages) public void OutputByConsole(IEnumerable outputSet, IEnumerable messages) foreach (var Out in outputSet) foreach (var msg in messages) Out.OutputString(msg); Console.ReadKey(); 运行!哈哈!yeah! 完成!参考资源如果你想了解跟多关于MEF的信息,下面有一些参考资源:Brad Abrams做的例子:http:/brad_/Projects/MEFSimpleSample/MEFDemoForBlog.zipMEF官方网站:/MEFMEF MSDN网站/mef本文参考文章/brada/archive/2008/11/07/managed-extensibility-framework-mef-demo.aspx使用MEF构建可扩展的Silverlight应用“托管扩展性框架(Managed Extensibility Framework,简称MEF),是微软.NET框架下为提高应用和组件复用程度而推出的,用于使组件能够最大化的重用。使用MEF能够使静态编译的.NET应用程序转换为动态组合,这将是创建可扩展应用、可扩展框架和应用扩展的好途径。它将做为.NET Framework 4.0的组成部分之一发布。现在,MEF也将被包含在Silverlight 4.0中。那么MEF是怎样工作的呢?简单分为三个步骤:Export (输出)Import (输入)Compose (组合) 简短说一下MEF的工作原理,MEF的核心包括一个catalog和一个CompositionContainer。category用于发现扩展,而container用于协调创建和梳理依赖性。每个可组合的Part提供了一个或多个Export,并且通常依赖于一个或多个外部提供的服务或 Import。每个Part管理一个实例为应用程序运行。查看原图(大图)下面我们做一个小型可扩展计算器示例来解释这三个过程1. 首先下载MEF框架包,Silverlight 4.0会自带,不过微软已经将其开源了。/MEF2. 创建一个Silverlight Navigate Application ,并添加程序集引用(MEF_Beta_2binSL目录下 System.ComponentModel.Composition.dll)在项目下添加两个类文件Package.cs和PackageCatalog.cs,这两个文件在最新的MEF版本中没有提供,主要用于加载silverlight的Xap包。这两个文件在MEF框架的Sample中提供了(MEF_Beta_2SamplesPictureViewerPictureViewer.Common),将这两个类的访问修饰符改为public, 添加后注意修改命名空间。3. 修改Home.cs 类代码usingSystem;usingSystem.Net;usingSystem.Windows;usingSystem.Windows.Controls;usingSystem.Windows.Documents;usingSystem.Windows.Ink;usingSystem.Windows.Inp

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论