之前在使用Prism框架时接触到了可扩展性框架MEF(Managed Extensibility Framework),体验到MEF带来的极大的便利性与可扩展性。

此篇将编写一个可组合的应用程序,帮助大家快速熟悉MEF并将其应用于实际项目中。

有关MEF中的名词含义及功能实现,请大家移步:火车票

介绍下将要编写的Demo程序(下图),使用winform开发。

  • 通过组合操作,程序动态加载可用部件进行组合操作。
  • 通过解体操作,程序卸载所加载的所有部件。

新建项目后需引用程序集:

System.ComponentModel.Composition

主程序的核心代码如下:

  public partial class Form1 : Form, IPartImportsSatisfiedNotification
  {
[ImportMany(AllowRecomposition = true)]
private IEnumerable<Lazy<IPlugin, IPluginMetadata>> plugins; private AggregateCatalog catalog;
private CompositionContainer container;
public Form1()
{
InitializeComponent();
if (catalog == null)
catalog = new AggregateCatalog();
this.container = new CompositionContainer(catalog);
this.container.ComposeParts(this);
} #region Implementation of IPartImportsSatisfiedNotification
public void OnImportsSatisfied()
{
flowLayoutPanel1.Controls.Clear();
if (plugins != null && plugins.Count() != )
{
plugins.ToList().ForEach((a) =>
{
Button btn = new Button();
btn.Cursor = System.Windows.Forms.Cursors.Hand;
btn.Width = ;
btn.Height = ;
btn.Text = a.Metadata.ThePluginName;
btn.Click += (d, b) => { a.Value.Run(); };
flowLayoutPanel1.Controls.Add(btn);
});
}
}
#endregion public void CompositionAction()
{
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
}
......
  }

1. IPartImportsSatisfiedNotification接口 : 在组件导入完成后,调用该接口中的方法(OnImportsSatisfied)。

2. MEF中最常用目录有三种:程序集目录(AssemblyCatalog),文件目录(DirectoryCatalog),聚合目录(AggregateCatalog)

程序集目录(AssemblyCatalog): 顾名思义可以向目录中添加程序集已存在类型中寻找可用于导入的部件。

var catalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());

文件夹目录(DirectoryCatalog):从文件夹中寻找可用于导入的部件

var catalog = new DirectoryCatalog("Extensions");

聚合目录(AggregateCatalog):可以向聚合目录包含上述两种方式

var catalog = new AggregateCatalog(
new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly()),
new DirectoryCatalog("Extensions"));

3. CompositionContainer : 组合容器,管理部件的组合并提供了一系列用于创建部件实例扩展方法等,详细资料

4. 目录与容器的一般使用方法:

    var catalog = new AggregateCatalog();
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

5. 导入:ImportAttribute 与 ImportManyAttribute

用于以下三种用途:字段,属性,方法

[import]
private IData _data; [import]
public IData Data{set;get;} [import]
public Action ClickAction;

ImportManyAttribute : 通过组合容器将所有符合契约的导出进行填充 (真别扭,说白了就是导入多个)

[ImportMany]
private IEnumerable<IPlugin> plugins;

AllowRecomposition : 是否允许重组

AllowRecomposition = true : 比如在程序运行的过程中,动态向聚合目录中添加可导出的部件,可以引发重组操作

catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));

需要注意的是:DirectoryCatalog 不会引发重组操作,可通过Refresh方法指定重组的策略。

6. System.Lazy<T> : MEF提供延迟导入。

下面来看一下,插件式如何实现的:

  [ExportPluginAttribute(typeof(IPlugin), ThePluginName = "TheFristPlugin")]
public class TheFristPlugin : IPlugin
{
public TheFristPlugin()
{
this.TheName = "TheFristPlugin";
}
#region Implementation of IPlugin public string TheName { get; set; } public void Run()
{
MessageBox.Show("TheFristPlugin");
} #endregion
}

1. 简单说一下:导入与导出之前的关系

一个基于MEF开发的可扩展的程序,在容器中必然有很多的导出(Export),而这些Export又是怎么样找到自己的归宿呢。

Export 与 Import 依靠一种契约,来确定对方是否是自己的兄弟,说白了就是接口,比如上述程序所定义的IPlugin接口

    public interface IPlugin
{
void Run();
}

使用 ExportAttribute 特性导出:

 [Export("count")]
public int count{ get{return ;} } [Export(typeof(Action))]
public void SendMsg(){return;} [Export]
public class Person{}

有一个需求,主程序要求插件必须要指定插件名称:

1. 在IPlugin接口中定义:Name字段

2. 使用元数据

3. 使用自定义导出特性(与第二种方案类似)

如何使用元数据?

1.定义元数据视图,此处视图使用接口类型

 public interface IPluginMetadata
{
string ThePluginName { get; }
}

2. 导出部件时,使用ExportMetaData特性

[ExportMetadata("ThePluginName", "TheFivePlugin")]
[Export(typeof(mef.test.wform.Interface.IPlugin))]
public class TheFivePlugin : mef.test.wform.Interface.IPlugin
{
public void Run()
{
MessageBox.Show("TheFivePlugin");
}
}

3. 导入元数据

[ImportMany(AllowRecomposition = true)]
private IEnumerable<Lazy<IPlugin, IPluginMetadata>> plugins;

4. 访问元数据

Lazy<T,TMetadata>.Value.Metadata

结束

到此为止,MEF 基本内容已讲解结束,如果有遗漏也请博友留言指出。

文章中很多都是白话,非官方语言,怎么理解的就怎么写,如果有不妥之处,还望各位博友指出。

新年快乐

浅谈可扩展性框架:MEF的更多相关文章

  1. 手撸ORM浅谈ORM框架之基础篇

    好奇害死猫 一直觉得ORM框架好用.功能强大集众多优点于一身,当然ORM并非完美无缺,任何事物优缺点并存!我曾一度认为以为使用了ORM框架根本不需要关注Sql语句如何执行的,更不用关心优化的问题!!! ...

  2. 手撸ORM浅谈ORM框架之Add篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  3. 手撸ORM浅谈ORM框架之Update篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  4. 手撸ORM浅谈ORM框架之Delete篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  5. 手撸ORM浅谈ORM框架之Query篇

    快速传送 手撸ORM浅谈ORM框架之基础篇 手撸ORM浅谈ORM框架之Add篇 手撸ORM浅谈ORM框架之Update篇 手撸ORM浅谈ORM框架之Delete篇 手撸ORM浅谈ORM框架之Query ...

  6. 【SSH学习笔记】浅谈SSH框架

    说在前面 本学期我们有一门课叫做Java EE,由陈老师所授,主要讲的就是Java EE 中的SSH框架. 由于陈老师授课风格以及自己的原因导致学了整整一学期不知道在讲什么,所以才有了自己重新学习总结 ...

  7. 浅谈angular框架

    最近新接触了一个js框架angular,这个框架有着诸多特性,最为核心的是:MVVM.模块化.自动化双向数据绑定.语义化标签.依赖注入,以上这些全部都是属于angular特性,虽然说它的功能十分的强大 ...

  8. 13.Object-C--浅谈Foundation框架常用的结构体

    ------- android培训.iOS培训.期待与您交流! ---------- 昨天学习了Foundation框架中常用的结构体,下面我简单的总结一下,如果错误麻烦请留言指正,谢谢! Found ...

  9. 2014-07-29 浅谈MVC框架中Razor与ASPX视图引擎

    今天是在吾索实习的第15天.随着准备工作的完善,我们小组将逐步开始手机端BBS的开发,而且我们将计划使用MVC框架进行该系统的开发.虽然我们对MVC框架并不是非常熟悉,或许这会降低我们开发该系统的效率 ...

随机推荐

  1. ORM原型概念

    ORM[Object-Relation-Mapping]对象关系映射. 这个名词已经出来好几年了.已经不陌生.  以前在项目中针对相对复杂业务逻辑时一般采用领域模型驱动方式进行业务概述,分析和建模. ...

  2. 苹果IOS系统SVN命令 同样适用于linux系统

    1.将文件checkout到本地目录svn checkout path(path是服务器上的目录)例如:svn checkout svn://192.168.1.1/pro/domain简写:svn ...

  3. LeetCode 176 Second Highest Salary mysql,select 嵌套 难度:1

    https://leetcode.com/problems/second-highest-salary/ Write a SQL query to get the second highest sal ...

  4. 通过MD5排除重复文件

    今天下载了好多美女图片壁纸,可是看了一下发现好多图片重复了,有强迫症的我必须把重复的都给剔除掉,首先想到的当然是百度了,问问度娘有没有什么图片去重的工具,搜了一下还真有.奈何本人智商捉急用不来这高级的 ...

  5. 关闭缓存和mmu(转)

    当设置完时钟分频以后,uboot就会执行cpu_init_crit汇编函数,这个函数的主要作用就是关闭缓存和mmu,然后调用lowlevel_init函数进行系统总线的初始化. 为什么启动的时候,需要 ...

  6. DDOS的攻击原理和防护指南(转)

    DDOS的攻击原理和防护指南 作者:冰盾防火墙 网站:www.bingdun.com 日期:2008-01-07   我们现在来分析DDOS的攻击原理.     首先,DDOS是英文Distribut ...

  7. transform:rotate在手机上显示有锯齿的解决方案

    transform:rotate 属于简单好用的效果,但在手机上显示时,会有比较明显锯齿. 解决方案也很简单, 利用外层容器的overflow:hidden 加上图片margin:-1px 就可以解决 ...

  8. [深入Python]__new__和__init__

    class A(object): def __init__(self): print "init" def __new__(cls,*args, **kwargs): print ...

  9. 推荐!国外程序员整理的 C++ 资源大全

    http://blog.jobbole.com/78901/ 关于 C++ 框架.库和资源的一些汇总列表,由 fffaraz 发起和维护. 内容包括:标准库.Web应用框架.人工智能.数据库.图片处理 ...

  10. memcache详解

    MemCache是一个自由.源码开放.高性能.分布式的分布式内存对象缓存系统,用于动态Web应用以减轻数据库的负载.它通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高了网站访问的速度. Me ...