文章缘起
要说写MEF中的导入导出,我想没有哪一篇文章可以比得上微软的官方文档了(至少是我看到的里面没有)。
个人强烈建议看MEF导入导出的人去看微软官方文档,文档地址:
个人喜欢用 Microsoft Help查看器(Help Viewer) 离线查看,如果你也喜欢这样,你可以直接在里面搜索MEF,找到特性化编程模型概述即可。
既然微软官方文档已经很完善了,那本文自然不会在写一遍,故本文更倾向与一篇快速索引参考文。
快速参考
导入导出基础
- 无参数导入导出,默认使用当前类或接口,示例如下:
示例中最后a有效,而ia无效;
public interface IA { }
/// <summary>
/// 等价于 [Export(typeof(A))]
/// </summary>
[Export]
public class A : IA { }
public class UseA
{
/// <summary>
/// 等价于 [Import(typeof(A))]
/// </summary>
[Import]
public A a { get; set; }
/// <summary>
/// 等价于 [Import(typeof(IA))]
/// </summary>
[Import]
public IA ia { get; set; }
}
- 含参数导入导出,要求类型和协定名完全匹配,未指定类型时,同上,使用当前声明的类或接口。
如下示例中,最终ib有效 ,而b是无效的。
public interface IB { }
[Export(typeof(IB))]
public class B : IB { }
public class UseB
{
[Import]
public B b { get; set; }
[Import]
public IB ib { get; set; }
}
- 延迟导入及导入多个;其中匹配类型时,均使用繁星内的类型。
在如下示例中,三个导入均有效。其中ImportMany主要用于多个具有相同协定名和类型的导出,如你有两个类使用了相同的类型和协定,用Import是会报错的,此时可以用ImportMany来处理。
public interface IC { }
[Export(typeof(IC))]
public class C : IC { }
public class UseC
{
[Import]
public Lazy<IC> ic { get; set; }
[ImportMany]
public IEnumerable<IC> iclist { get; set; }
[ImportMany]
public IEnumerable<Lazy<IC>> icllist { get; set; }
}
元数据
元数据可以简单理解为:针对具有相同协定和类型的导出,添加元数据来区分它们。
继承
在MEF中使用InheritedExport来设置继承导出,在继承结构中,导出的匹配类型为父类/接口的类型,示例如下:
在如下代码中,最后id是有效的,d是无效的,即类型D的导出继承ID,使用的类型为ID。
[InheritedExport]
public interface ID { }
public class D : ID { }
public class UseD
{
[Import]
public D d { get; set; }
[Import]
public ID id { get; set; }
}
结语
本文主要列出了最常用的导入导出参考,详细信息及更多扩展内容还是建议看微软官方文档:特性化编程模型概述 (MEF)。