1.什么是MEF。
MEF,全称是Managed Extensibility Framework。它是.NET Framework4.0的一个类库,其主要目的是为了创建可扩展的应用程序。按照官方说法就是“用于简化在部署后可由第三方进行扩展的可组合系统的设 计。MEF 可使您的应用程序具有开放性,从而允许应用程序开发人员、框架编写者以及第三方扩展程序不断引入新功能”;
2.MEF的主要步骤。
1)第一步,定义导出Export。
指定程序通过相应的契约进行通信。可以有多个通信契约。而且通信契约可以是任何一个类。例如
1
2
3
4
5
6
7
8
9
10
|
[Export(
typeof
(IMEFFirst))]
[Export(
typeof
(Form))]
[ExportMetadata(
"Name"
,
"FormMEFTest1"
)]
public
partial
class
FormMEFTest1 : Form, IMEFFirst
{
public
FormMEFTest1()
{
InitializeComponent();
}
public
string
ControlTitle {
get
{
return
"FormMEFTest1"
; } }
}
|
这里面。IMEFFirst是只定义的一个接口,其定义相当的简单
1
2
3
|
public
interface
IMEFFirst
{
string
ControlTitle {
get
;}
}
|
而Form则是窗体默认继承的父类。而ExportMetadata则是元数据,可以是一些对部件的描述。
2)第二步,定义导入Import
指出导出的位置。一般情况下,写法如下
1
|
[Import]
public
IMEFFirst IMEFFirstImportedMainFormContract {
get
;
set
; }
|
|
如果有很多个部件需要导入,则必须用ImportMany,实现多个加载
|
1
|
[ImportMany]
public
Lazy<Form, IDictionary<
string
,
object
>>[] ImportedMainFormContracts {
get
;
set
; }
|
|
|
Lazy<T, TMetadata>是延迟加载的意思,具体说明点击查看。其中Lazy<T>是可延迟实例的实例化,直至访问 Lazy 的 Value 属性。而Lazy<T, TMetadata>更是继承并扩展于Lazy<T>,
其可以在以允许在不实例化基础导出的情况下访问导出元数据。这句话的意思是,这里面实例的通过后面的TMetadata的类型,来获取元数据,这里用过的是IDictionary<string, object>,
也是就是通过字典的形式来导出。例如,可以这么使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
foreach
(
var
export
in
this
.ImportedMainFormContracts)
{
string
menuTitle = export.Metadata[
"Name"
]
as
string
;
if
(String.IsNullOrEmpty(menuTitle))
{
return
;
}
if
(menuTitle == thisItemTitle)
{
Form frm = export.Value
as
Form;
if
(frm ==
null
) {
return
; }
frm.Show(
this
);
return
;
}
}
|
export.Metadata["Name"],这种写法就是因为其前面我们这样定义元数据视图:IDictionary<string, object>
3)第三步,使用
首先,通过下面这段方法,实现对newContainer的实例化。下面这个方法实现的功能是从指定目录下导入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
private
CompositionContainer newContainer;
/// <summary>
/// 加载指定路径的dll,并返回CompositionContainer
/// </summary>
/// <param name="strPath">DLL路径</param>
/// <returns></returns>
private
CompositionContainer GetNewContainer(
string
strPath)
{
AggregateCatalog aggregateCatalog =
new
AggregateCatalog();
//var thisAssembly =new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
//aggregateCatalog.Catalogs.Add(thisAssembly);//加载此程序的程序集
aggregateCatalog.Catalogs.Add(
new
DirectoryCatalog(strPath));
//动态加载指定目录
CompositionContainer container =
new
CompositionContainer(aggregateCatalog);
return
container;
}
|
而后,通过
|
newContainer.ComposeParts(
this
);
|
这个语句实现对前面指定的[ImportMany] 处ImportedMainFormContracts 的赋值。