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

[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property | AttributeTargets.Method 
| AttributeTargets.Class, AllowMultiple=true, Inherited=false)]
public class ExportAttribute : Attribute
{ }

果然,支持这四种成员,另外,在同一个目标上可应用多次该特性但是它不支持继承,如果想继承则需使用ExportAttribute的派生类InheritedExportAttribute来实现。

组合部件导出

组合部件导出被用在当需要导出它自己的时候。在前面的例子中,我们使用的都是这种方式。

    [Export(typeof(IMessageSender))]
class EmailSender : IMessageSender
{
public void Send(string msg)
{
Console.WriteLine("Email Sent:"+msg);
}
}

这里,我们需要将EmailSender部件自身导出,其实就是类级别的导出。

属性导出

组合部件也可以导出属性。属性导出有这么几个优点:

  • 它允许导出像核心的CLR类型这样的密封类,或者是其它第三方类
  • 它允许将导出创建方式和导出解耦。例如,导出运行时为你创建的已经存在的HttpContext部件
  • 它允许在相同的组合部件中有一些相关的exports,例如一个DefaultSendersRegistry组合部件默认有一系列senders属性导出
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel.Composition.Hosting; namespace ExportsDeclaring
{
class Program
{
[Import]
public UsesTimeout UsesTimeout { get; set; }
static void Main(string[] args)
{
Program p = new Program();
p.Compose();
Console.WriteLine(p.UsesTimeout.Timeout);
Console.ReadKey();
}
void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this, new UsesTimeout(),new Configuration());
}
}
public class Configuration
{
[Export("Timeout")]
public int Timeout
{
get { return int.Parse(ConfigurationManager.AppSettings["Timeout"]); }
}
}
[Export]
public class UsesTimeout
{
[Import("Timeout")]
public int Timeout { get; set; }
}
}

在上面的代码之前,需要先在配置文件中配置key为Timeout的AppSetting,例如:<add key="Timeout" value="5000"/>。

输出为:

方法导出

方法导出是用在一个部件要将它的方法导出的地方。通过在导出契约中指定委托的方式来导出方法。方法导出有下面的几点好处:

  • 它允许对于要导出的方法进行细粒度的控制。例如,一个规则引擎可能倒入一系列可插拔的方法导出部件。
  • 它屏蔽了调用者对于类型的了解。
  • 它可以由代码生成器生成,你不需要处理其它的导出部件。

注意:由于框架的限制,方法导出最多不能超过四个参数。

在下面的例子中,MessageSender类将它的Send方法导出为一个Action<string>委托,这个Processor导入了这个相同的委托。

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 ExportsDeclaring
{
class Example
{
[Import]
public Processor Processor { get; set; }
static void Main()
{
Example e = new Example();
e.Compose();
e.Processor.Send();
Console.ReadKey();
}
void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this, new Processor(), new MessageSender());
}
}
public class MessageSender
{
[Export(typeof(Action<string>))]
public void Send(string msg)
{
Console.WriteLine(msg);
}
}
[Export]
public class Processor
{
[Import(typeof(Action<string>))]
public Action<string> MessageSender { get; set; } public void Send()
{
MessageSender("Processed");
}
}
}

输出为:

你也可以使用一个简单的字符串契约来导入导出。但是,当进行方法导出时,你必须得提供一个类型或者字符串七月名称,而不能留空。

导出继承

MEF支持在一个基类或者接口中定义的导出将自动地被它的实现类继承的能力。这对于与那些想要利用MEF来发现而不是要求修改已有的客户代码的传统框架来说是很理想的。为了提供这种能力需要使用[System.ComponentModel.Composition.InheritedExportAttribute]。例如下面的ILogger接口有一个[InheritedExport],Logger实现了该接口,因此自动地导出了ILogger。

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 ExportsDeclaring
{
class Example1
{
[Import]
public ILogger Logger { get; set; }
static void Main()
{
Example1 e = new Example1();
e.Compose();
e.Logger.Log("Logging");
Console.ReadKey();
}
void Compose()
{
var container = new CompositionContainer();
container.ComposeParts(this, new Logger());
}
}
[InheritedExport]
public interface ILogger
{
void Log(string msg);
}
public class Logger : ILogger
{
public void Log(string msg)
{
Console.WriteLine(msg);
}
} }

发现非公有的组合部件

MEF支持公有和非公有部件的发现。你不需要做任何事情来启用该行为。请注意:在并不完全受信任的环境中(包括sliverlight),非公有的组合将不被支持。

MEF初体验之三:Exports声明的更多相关文章

  1. MEF初体验之五:Lazy Exports

    在一个部件组合中,导入将触发一个部件或者多个部件的实例化,这些部件暴露了所需原请求部件的必要的导入.对于一些应用程序来说,延迟实例化-防止图结构下的递归组合-可能对于将创建一个长久复杂的开销很大而不必 ...

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

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

  3. MEF初体验之二:定义组合部件和契约

    组合部件 在MEF中,一个组合部件就是一个组合单元,组合部件"出口"其它组合部件需要的服务并且从其它部件"进口"需要的服务.在MEF编程模型中,为了声明组合部件 ...

  4. MEF初体验之七:Using Catalogs

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

  5. MEF初体验之一:在应用程序宿主MEF

    在MEF出现以前,其实微软已经发布了一个类似的框架,叫MAF(Managed Add-in Framework),它旨在使应用程序孤立和更好的管理扩展,而MEF更关心的是可发现性.扩展性和轻便性,后者 ...

  6. MEF初体验之十二:Composition Batch

    一个MEF容器实例是不可变的.如果catalog支持改变(像观察一个目录的改变)或是如果你的代码在运行时添加或移除部件,改变都可能发生.以前,你不得不作出改变并在组合容器上调用它的组合方法.在Prev ...

  7. MEF初体验之十一:查询组合容器

    查询组合容器 组合容器暴露了几个get exports的重载方法和导出对象和对象集合.你需要注意下面的行为: 当请求单个对象实例时,如果未发现导出,一个异常将被抛出 当请求单个对象实例时,如果发现超过 ...

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

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

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

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

随机推荐

  1. phpmailer【PHP邮件】的用法

    第一,需要下载PHPMailer文件包phpmailer. http://phpmailer.sourceforge.net/ 第二,确认你的服务器系统已经支持socket ,通过phpinfo(); ...

  2. 【足迹C++primer】52、,转换和继承虚函数

    转换和继承,虚函数 Understanding conversions between base and derived classes is essential to understanding h ...

  3. Windows Phone开发(34):路径标记语法

    原文:Windows Phone开发(34):路径标记语法 如果你觉得前面所讨论的绘制各种几何图形的方法过于复杂,那么,今天我们也来一次"减负"吧.当然,我们是很轻松的,本教程是不 ...

  4. Cocos2d-x 脚本语言Lua中的面向对象

    Cocos2d-x 脚本语言Lua中的面向对象 面向对象不是针对某一门语言,而是一种思想.在面向过程的语言也能够使用面向对象的思想来进行编程. 在Lua中,并没有面向对象的概念存在,没有类的定义和子类 ...

  5. (转)FFMPEG解码流程

    http://www.douban.com/note/228831821/ FFMPEG解码流程:     1. 注册所有容器格式和CODEC: av_register_all()     2. 打开 ...

  6. 高性能 Socket 组件 HP-Socket v3.2.1-RC2 公布

    HP-Socket 是一套通用的高性能 TCP/UDP Socket 组件,包括服务端组件.client组件和 Agent 组件,广泛适用于各种不同应用场景的 TCP/UDP 通信系统,提供 C/C+ ...

  7. 得到Android系统语言设置

    private int g_lag = 1; // String filename = Locale.getDefault().getLanguage(); if (filename != null) ...

  8. How to fix Column 'InvariantName' is constrained to be unique 解决办法!

    Introduction When you build a web project that uses Enterprise Library Community for the Application ...

  9. 实现app上对csdn的文章列表上拉刷新下拉加载以及加入缓存文章列表的功能 (制作csdn app 四)

    转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/23698511 今天继续对我们的csdn客户端未完成的功能进行实现,本篇博客接着客 ...

  10. 基于Tkinter利用python实现颜色空间转换程序

    主要基于colorsys实现,例子是从hls转换到rgb,假设要换颜色空间非常easy仅仅须要改动一个函数 用到了Scale和Canvas组件 代码例如以下: from Tkinter import ...