MEF应用(2)

本文介绍了Microsoft Extensibility Framework (MEF) 的核心概念及其工作原理。MEF是一种轻量级框架,通过特性化编程模型实现了组件和服务的动态发现与组合。文章详细解释了导出(Export)与导入(Import)部件的匹配过程,以及如何利用动态导入、延迟导入等多种导入类型提高程序的灵活性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

为什么要使用MEF?

1.它解决了扩展性的问题(这是第一位的,不然我们就没必要介绍MEF了);

2.它轻量级,使用时只需要引用一个dll库; System.ComponentModel.Composition

3.扩展性不是通过配置文件实现,而是使用特性化编程模型

4.该框架是开源的,可在codeplex上下载源码;

5.它是微软开发的(这一点很重要)。

 

MEF的工作原理:

  MEF不同于显式注册可用组件的做法,在MEF中组件被视为部件。这些部件主要有“导入”(Import)部件和“导出”(Export)部件,此外MEF提供了一个组合容器(ComposeContainer),容器会发现指定Catalog的导入导出部件,并按Contract(协定)、Metadata(元数据)等对导入和导出部件进行组合。

上述文字已经把MEF中涉及的相关概念指出了,下面具体说明一下:

Export(导出): “Export”也就是我们常说的组件或者模块或者服务,它是部件向容器中的其他部件提供的一个值、功能或服务等;

Import(导入): "Import”,既扩展点,是组件,服务等接入系统的窗口,是部件向要通过可用导出满足的容器提出的要求,MEF 支持若干导入类型,其中包括动态导入、延迟导入、必备导入和可选导入;

Contract(协定):是Export和Import的一种约定,一种协议,只有Contract相匹配的Import和Export部件才能组装成功;

Catalog(目录):为了发现可用于组合容器的部件,组合容器将使用“Catalog”。 目录是一个对象,通过它发现可用部件, MEF 提供了用于从提供的类型、程序集或磁盘路径创建Catalog。

Compose(组合):在MEF中,容器将导入与导出匹配的这一过程我们称之为组合,部件由 MEF 组合,MEF 将部件实例化,然后使导出程序与导入程序相匹配。

 

 

 

 

 

 

 

 

 

导入和导出

 

前言:

MEF不同于其他IOC容器(如:Castle)很重要的原因在于它使用了特性化编程模型,何为特性化编程这里不细究,简单说明下两个概念:“特性”和“编程模型”:

  特性(Attribute):举例来说就是我们在开发过程中在类上标记的如:[Serializable]的标签。

  编程模型(Programming Model):MEF中的编程模型是定义 MEF 所操作的概念性对象集的特定方法。MEF默认使用特性化编程模型,但是用户也可自定义编程模型。

  导入(Import),导出(Export)是MEF扩展性机制实现的基础,是非常重要的两种部件。MEF中导入、导出部件均是通过特性来确定的(如:标记有[Export]特性的我们称之为导出部件)。本文简单的介绍下MEF中得导入和导出。

 

 

Export 特性可修饰类、字段、属性或方法,而 Import 特性可修饰字段、属性或构造函数参数。导入和导出的匹配必须要有相同的Contract,Contract有两部分组成:ContractName(名称)和ContractType(类型),只有名称和类型都完全相同,才会认为导出能够满足特定导入

 

View Code 
 public interface ILog
 {
      void Log(Exception ex);
 }
 
 //导出的类型为ILog[Export(typeof(ILog))]
 pulic class FileLog:ILog
 {
      public void Log(Exception ex)
      {
      }
 }
 
 pulic class MyClass
 {
         //导入的类型默认为ILog,可以与导出匹配    [Import]
     pulic Ilog MyLog
     {
         get;
         set;
     }
 }


 

导入的类型:

MEF中导入的类型包括了:动态导入、延迟导入、必备导入和可选导入。

动态导入:使用dynamic关键字进行导入,协定类型从 dynamic 关键字推断而出,则它将与任何协定类型匹配。所以在使用动态导入时必须指定协定名称,否则将未匹配任何导出

 

1 public class MyClass
2 {
3     [Import(“MyLog”)]
4     public dynamic MyLog{ get; set; }
5 }

 

延迟导入:我们知道延迟加载,那么延迟导入同延迟加载的作用一样:导入和导出匹配时不会立即实例化对象,延迟导入需要使用Lazy<T>来声明导入:

 

1 public class MyClass
2 {
3     [Import]
4     public Lazy<ILog> MyLog { get; set; }
5 }

 

必备导入:在实际工作中我们经常会用到依赖注入,通过构造函数将我对象注入到本类中是依赖注入的一种形式,MEF也可以完成构造注入。

导出部件通常由组合引擎/容器创建,默认情况下,在创建部件时,组合引擎将使用无参数的构造函数。要想使用自定义构造函数完整对象的注入需要使用特性:ImportingConstructor。使用必备导入时必须同时提供默认构造和ImportingConstructor的构造方法,否则将出错.

 

public class MyClass 
 {
     private ILog _myLog;
 
     public MyClass() { }
 
     [ImportingConstructor] 
     public MyClass(ILog myLog) 
     {
         _myLog = myLog;
     }
 }

可选导入:在MEF中如果导入得不到匹配将会组合失败,在需要容错的情况时,可以使用AllowDefault 属性指定导入为可选:[Import(AllowDefault = true)]。这样即使导入没有得到匹配也不会影响组合容器对部件的组合。

导入多个对象:导入和导出可以支持一对多的关系,使用ImportMany特性可以导入多个服务(导出),使用ImportMany标记的导入始终是可选导入。

1 public class MyClass
2 {
3     [ImportMany]
4     public IEnumerable<ILog> MyLogs { get; set; }
5 }

导入和导出的继承

导入的继承:导入始终由子类继承,子类拥有和父类相同的导入。

导出的继承:使用Export特性的导出部件始终不能被继承,如果想要导出部件可以被继承需要使用关键字:InheritedExport,子类将提供与父类相同的导出(包括ContractName和ContractType)。但是InheritedExport只能标记在类上,也就是说成员导出永远不能被继承。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值