MEF在.net中实现插件功能
2015-10-10 (2015-10-10更新)
MEF简介
MEF 可以比较方便的在.net程序中实现插件技术,相比MAF等技术要简单易用,对于小型项目建议使用MEF。MEF通过接口暴露公开方法,插件内继承接口的类可以通过[Export]特性公开,宿主程序通过建立接口类型的属性(必须有[Import]特性)调用插件方法。插件可以和主程序不在同一个程序集,插件也可以在需要的任何时候添加到主程序。
MEF组成
MEF主要有4个部分组成
- 接口部分:定义插件接口
- 出口部分:也就是插件,其实就是实现了插件接口并带有Export特性的类
- 入口部分:通过入口可以调用插件对象,带有Import特性且声明为插件接口类型的属性
- 容器部分:容器加载出口部分也就是插件,并把插件映射到入口部分
在容器把出口部分映射到入口部分后,宿主程序可以通过调用入口部分调用插件对象或函数。
MEF使用步骤
定义插件接口
根据需要定义Interface,Interface主要用于暴露插件的属性或方法。在接口中也可以定义获取插件中的UI控件、菜单项的方法或属性。
编写入口/import
- 依赖接口部分
- 在入口部件里声明接口类型的属性或方法,并添加Import特性
编写出口/export/插件
- 依赖接口部分
- 编写至少一个实现接口的类,并添加Export特性
- 可以在单独的程序集/dll里
- 可以在程序完成后,无源代码的情况下加入更多的出口,即程序可以动态加载插件
通过Batch可以动态加载或卸载出口部件(出口部件是一个可以包含插件程序集信息列表的类)。
建立容器container
- 容器依赖入口部件,不依赖出口部件
- 一般container在宿主程序内
- 创建代码为:container=
new CompostionContainer(category);
,需要先建立类别catelog- category里包含出口部件/插件信息
- DirectoryCatelog:从指定目录获取部件
- AssemblyCtelog:
容器组合出口/export和入口/import(映射出口到入口)
- composeParts(入口部件实例,可以是数组)
- compose(batch)
宿主程序调用入口
- 依赖入口部件
- 依赖容器,因为宿主运行插件时需要调用容器先执行compose操作
- 通过入口部件实例直接调用带Import特性的属性或方法
- 所有入口都映射到了出口程序上才能正确运行,否则会抛出异常
组织结构
- 插件在单独的程序集中
- 插件接口推荐放在单独的程序集中,因为出口部分和入口部分都依赖接口部分
- 一般情况下宿主程序直接调用容器和入口部分(即三者在同一个程序集中)
- 入口和容器不在宿主程序集也可以通过reference调用,不一定必须在同一个程序集
代码实例
待续…