组合部件

在MEF中,一个组合部件就是一个组合单元,组合部件"出口"其它组合部件需要的服务并且从其它部件"进口"需要的服务。在MEF编程模型中,为了声明组合部件的"出口"和"进口",使用的是ExportAttribute和ImportAttribute。一个组合部件至少应该包含一个[Export]。组合部件既可以被显式的添加到Container,也可以通过使用Catalogs来创建。MEF附带的默认的Catalogs是通过[Export]来识别组合部件的。

契约

组合部件并不直接依赖另一个组合部件,而是依赖一个由字符串标识的契约。每一个[Export]都有一个契约,每一个[Import]都声明了它需要的契约。Container使用契约来Import部件匹配Export组件。如果未指定契约,MEF将隐式地将类型的全限定名作为契约。如果被传递的是一个类型,也将采用上面的方式。

注意:默认是传递一个type而不是一个字符串。尽管契约可以是任意的字符串,但是这可能会导致歧义。例如,一个名为"Sender"的契约可能会和另一个类库的名为"Sender"的契约重叠。处于这样的原因,如果你需要指定一个字符串契约,建议使用包含公司名称的命名空间来限定,例如 "Contoso.Exports.Sender"

在下面的code snippet中,所有的export契约都是等价的。

    [Export]
class Exporter { }
[Export(typeof(Exporter))]
class Exporter1 { }
[Export("PartsAndContracts.Exporter")]
class Exporter2 { }

接口/抽象契约

一个通用的模式是为一个组合部件export一个接口或者一个抽象类型的契约而不是一个具体的类型。这允许import组件完全不耦合于将要import的export组件的具体实现,从而导致关注点的分离。例如,下面你可以看到有两个都export了IMessageSender接口的Sender实现。这个Notifier类import一个IMessageSender类型的集合,我们调用分别调用每一个的Send()方法。现在一个的message senders可以很容易地被添加到系统中。

using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Text;
using System.Threading.Tasks; namespace PartsAndContracts
{
class Program
{ static void Main(string[] args)
{
Program p = new Program();
Notifier noter = new Notifier();
var container = new CompositionContainer();
container.ComposeParts(noter, new EmailSender(), new TcpSender(),new PhoneSender());
noter.Notify("Hi,MEF");
Console.WriteLine("-----------------");
noter.MessageSender.Send("Hi,MEF");
Console.ReadKey();
}
}
class Notifier
{
[ImportMany]
public IEnumerable<IMessageSender> Senders { get; set; }
[Import("PhoneSender")]
public IMessageSender MessageSender { get; set; }
public void Notify(string msg)
{
foreach (var item in Senders)
{
item.Send(msg);
}
}
}
interface IMessageSender
{
void Send(string msg);
}
[Export(typeof(IMessageSender))]
class EmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Email Sent:"+msg);
}
}
[Export(typeof(IMessageSender))]
class TcpSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("TCP Sent:"+msg);
}
}
[Export("PhoneSender",typeof(IMessageSender))]
class PhoneSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Phone Sent:" + msg);
}
}
}

如图显示:

在上面例子中,组合部件通过type契约使得export的EmailSender和TcpSender实例import到Senders属性,通过string identifier契约使得PhoneSender部件和MessageSender匹配。

MEF初体验之二:定义组合部件和契约的更多相关文章

  1. Java8初体验(二)Stream语法详解(转)

    本文转自http://ifeve.com/stream/ Java8初体验(二)Stream语法详解 感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com上篇文章Java8初体验(一 ...

  2. Java8初体验(二)Stream语法详解---符合人的思维模式,数据源--》stream-->干什么事(具体怎么做,就交给Stream)--》聚合

    Function.identity()是什么? // 将Stream转换成容器或Map Stream<String> stream = Stream.of("I", & ...

  3. MEF 编程指南(二):定义可组合部件和契约

    可组合部件(Composable Parts)   在 MEF 内部可组合部件是一个可组合单元.可组合部件导出其他可组合部件需要的服务,并且从其他可组合部件导入服务.在 MEF 编程模型中,可组合部件 ...

  4. Java8初体验(二)Stream语法详解

    感谢同事[天锦]的投稿.投稿请联系 tengfei@ifeve.com 上篇文章Java8初体验(一)lambda表达式语法比 较详细的介绍了lambda表达式的方方面面,细心的读者会发现那篇文章的例 ...

  5. MEF初体验之七:Using Catalogs

    MEF特性化编程模型的价值主张之一是通过catalogs动态发现部件的能力.Catalogs允许应用程序很容易地消费那些通过[Export]已经自我注册的exports. Assembly Catal ...

  6. MEF初体验之四:Imports声明

    组合部件使用[System.ComponentModel.Composition.ImportAttribute]特性声明导入.与导出类似,也有几种成员支持,即为字段.属性和构造器参数.同样,我们也来 ...

  7. MEF初体验之三:Exports声明

    组合部件通过[ExportAttribute]声明exports.在MEF中,有这么几种成员可声明exports的方式:组合部件(类).字段.属性和方法.我们来看下ExportAttribute类的声 ...

  8. MEF初体验之十:部件重组

    一些应用程序被设计成在运行时可以动态改变.例如,一个新的扩展被下载,或者因为其它的多种多样的原因其它的扩展变得不可用.MEF处理这些多样的场景是依赖我们称作重组的功能来实现的,它可已在最初的组合后改变 ...

  9. MEF初体验之九:部件生命周期

    理解MEF容器中部件的生命周期及其含义是非常重要的.鉴于MEF重点在开放端应用程序,这将变得尤其重要的,一旦app ships和第三方扩展开始运行,作为应用程序的开发者将很好地控制这一系列的部件.生命 ...

随机推荐

  1. Oracle连接池

    原由:许多用户可能在查询相同的数据库以获取相同的数据.在这些情况下,可以通过使应用程序共享到数据源的连接来提高应用程序的性能.否则,让每个用户打开和关闭单独的连接的开销会对应用程序性能产生不利影响.这 ...

  2. 【前段开发】行内元素和块级元素总结(HTML CSS)

    块级元素 <address> information on author <blockquote> long quotation <button> push but ...

  3. 学习笔记 Android.mk 搜索自己主动

    最近一直Android.mk这是什么一个令人沮丧的夜晚,点击此处记录. ios你担心更多.不管那么多.xcode自己解决. 文本工具:MACVIM(文本编辑工具 很有用 你可以清楚地分辨tab 和Sp ...

  4. 概率dp专辑

    求概率 uva11021 http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...

  5. C#遍历FTP文件夹/下载

    原文链接:http://blog.csdn.net/ou8811/article/details/5295780 整个程序大致可以分为2个部分,第一部分是实现单个文件下载的方法 [c-sharp] v ...

  6. 推荐15个月 Node.js 开发工具

    Node.js 越来月流行.这个基于 Google V8 引擎建立的平台, 用于方便地搭建响应速度快.易于扩展的网络应用.在本文中.我们列出了2015年最佳的15个 Node.js 开发工具.这些工具 ...

  7. leetcode先刷_Remove Duplicates from Sorted List II

    删除重复节点列表中的.假设所有val如果仅仅是为了保持一个非常easy.应承担重复val节点被删除话.要保持pre节点.每当你想保存这pre问题节点,应该head节点可以被取出,好了,没问题边境控制. ...

  8. dbus 和 policykit 实例篇(python) ()转

    使用policykit 的程序一般都有一个dbus daemon程序来完成相关操作,这个dbus daemon 会在系统注册一个system bus 服务名,用于响应要求root privileged ...

  9. 【SICP读书笔记(四)】练习2.27 --- 表序列reverse的扩展:树结构的deep-reverse

    题目要求是,修改练习2.18所做的reverse过程,得到一个deep-reverse过程.它以一个表为参数,返回另一个表作为值,结果表中的元素反转过来,其中的子树也反转. 例如: (define x ...

  10. 左右xcode的重构选项的一些理解

    Rename(重命名):对标示符进行重命名,以获得更好的代码可读性,这些标示符包含类,方法或者函数的名称. Extract(抽取):将你在XCode种选择的代码抽取到一个新的方法或函数中. Creat ...