MEF(Management Extensibility Framework)
MEF是Scott Guthrie在PDC2008大会中以一个Visual Studio的Editor插件首次展示的,有兴趣的话,可以看看相关的PDC2008r 视频,从初衷上来看,MEF是为了针对第三方插件扩展问题和解决自发觉、非配置的插件的开放式系统,而其目标也是为了替换OLE, COM之类的技术,并且在初期的应用也是和SliverLight一起解决Model、View之间解耦问题。
显而易见,MEF是为了解决接口的扩展问题,提到接口,就不能不提到Contract Programming,而事实上MEF也是基于这个来实现,下面我们可以看看一个简单的例子。
首先要定义一个Contract,
public interface IMessageSender
{
void send(String message)
}
在这里,我们定义了一个interface,并且规范了他的behavior,也就是send方法。
接下来,我们就要定义一个符合这个Contract的插件,
public class MailSender : IMessageSender
{
public void send(String message)
{
//具体实现:使用SMTP发送消息
}
}
到这里,Contract和基于Contract的实现都已经好了,接下来,我们就需要把这个插件的暴露出来,加入下面这个Attribute就可以了。
[Export(typeof(IMessageSender))]
public class MailSender : IMessageSender
{
public void send(String message)
{
//具体实现:使用SMTP发送消息
}
}
那么如何将这个插件引入呢,那么就需要在应用程序中事先定义一个预置的扩展点,下面这个示例简单的把这个类型的插件作为属性预置在应用程序中。
[Import]
public IMessageSender MessageSender{get; set;}
在程序中如何动态的使用这些插件呢,MEF提供了Catalog, Container来动态组合使用插件。
// 初始化插件目录
AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
// 初始化容器
var container = new CompositionContainer(catalog);
// 动态加载插件
container.ComposeParts(this);
从表面上来看,它很象是一个IoC的微容器,但是与Enterprise Library中标准的IoC容器UNITY相比,有什么区别呢。
从它的开发者Glenn Block的博文 Should I use MEF for my general IoC needs?中,归纳了以下五不规范提请开发人员注意:
如果希望由统一的配置来管理POCOs(plain old CLR objects),那么不要选择MEF;
你是否需要AOP拦截来实现注入logging和自动的事务管理,可MEF本身没有这方面的功能支持;
不支持开放的范型;
MEF仅仅包含两种生存周期模型,共享和非共享的,如果你需要自定义生存周期,比如说针对线程或各个会话,那么你需要手工设置容器的层次结构,尽管那样虽然可行,但是要大量的时间;
不支持参数化构建。
完整的程序示例:
1 using System.ComponentModel.Composition;
2 using System.ComponentModel.Composition.Hosting;
3 using System.Reflection;
4 using System;
5
6 public class Program
7 {
8 [Import]
9 public IMessageSender MessageSender { get; set; }
10
11 public static void Main(string[] args)
12 {
13 Program p = new Program();
14 p.Run();
15 }
16
17 public void Run()
18 {
19 Compose();
20 MessageSender.Send("Message Sent");
21 }
22
23 private void Compose()
24 {
25 AssemblyCatalog catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
26 var container = new CompositionContainer(catalog);
27 container.ComposeParts(this);
28 }
29 }
30
31 public interface IMessageSender
32 {
33 void Send(string message);
34 }
35
36 [Export(typeof(IMessageSender))]
37 public class EmailSender : IMessageSender
38 {
39 public void Send(string message)
40 {
41 Console.WriteLine(message);
42 }
43 }
参考资料:
MEF的官网 http://mef.codeplex.com/
Glenn Block的文章 Should I use MEF for my general IoC needs? http://codebetter.com/blogs/glenn.block/archive/2009/08/16/should-i-use-mef-for-my-general-ioc-needs.aspx