{
public enum CreationPolicy
{
Any = 0 ,
Shared = 1 ,
NonShared = 2 ,
}
}
Any表示可共享或不共享,部件的实例用MEF容器根据不同的请求需求自动控制;Shared表示共享部件,既Shared类型的插件部件可以在多个MEF组合容器中共用;其次是NonShared类型,表示不共享部件实例,每当有新的请求就会创建一个新的对象实例。在MEF中,通过PartCreationPolicyAttribute特性实现对部件的生命周期配置。
{
string GetBookName();
}
[PartCreationPolicy(CreationPolicy.Any)]
[Export( typeof (IBookService))]
public class MEFBookService : IBookService
{
public string GetBookName()
{
return " 《MEF程序设计指南》 " ;
}
}
[PartCreationPolicy(CreationPolicy.NonShared)]
[Export( typeof (IBookService))]
public class ASPNETBookService : IBookService
{
public string GetBookName()
{
return " 《ASP.NET项目案例》 " ;
}
}
[PartCreationPolicy(CreationPolicy.Shared)]
[Export( typeof (IBookService))]
public class SLBookService : IBookService
{
public string GetBookName()
{
return " 《Silverlight高级编程》 " ;
}
}
如上示例代码分别演示了使用Any、Shared及NonShared类型的生命周期托管类型对不同的对象进行导出部件配置。接下来通过导入部件并加入生命周期托管筛选,详细应用如下代码块所示:
{
[ImportMany(RequiredCreationPolicy = CreationPolicy.Shared)]
public List < IBookService > Service { get ; set ; }
public MainPage()
{
InitializeComponent();
CompositionInitializer.SatisfyImports( this );
// 得到成功装配的部件总数为2,因为Any类型是可以共存于多个MEF容器的。
int count = Service.Count;
}
}
表面上看去和上一篇指南中介绍的部件的筛选过滤功能非常相似,不同是的过滤筛选是通过自定义筛选策略实现,而这里是通过MEF生命周期范围托管来实现的。在实际的项目开发中需根据不同的应用场景确定具体的技术实现方案。
除了容器部件的生命周期托管,我们也得考虑部件容器自身的生命周期,容器什么时候释放资源,时候时候释放其内部部件的资源占用等。为了提高系统的整体性能,MEF建议将每一个可导入部件实现IDisposable 接口,用于资源的占用处理,如果部件从MEF容器中移除那么所对应占用的资源也会自动的清理。这里需要注意一点,就是当组合容器被释放掉后迟延加载的操作就不能再继续工作了,会抛出System.ObjectDisposedException异常。
如上图所示,MEF的容器是具有层次结构的,最高层级容器为程序直接应用级容器,可以通过以下的代码获取到。
var container = new CompositionContainer(catalog);
位于顶级容器之下的子容器,通常来说都是控制着一些可动态装配的部件对象,如同上一篇指南中介绍到使用过滤器筛选部件的应用案例,通过过滤表达式从顶级容器中进行筛选,得出了新的MEF容器child,child托管着根据条件过滤筛选出来的所有结果部件对象。详细代码如下:
var catalog = new AssemblyCatalog( typeof (MainPage).Assembly);
// 将目录装载进MEF组合容器
var parent = new CompositionContainer(catalog);
// 通过元数据过滤筛选出元数据名称为"UC"值为"CC"的组合部件
var filteredCat = new FilteredCatalog(catalog,
def => def.Metadata.ContainsKey( " UC " ) &&
def.Metadata[ " UC " ].ToString() == " CC " );
var child = new CompositionContainer(filteredCat, parent);
var control = child.GetExportedValue < UserControl > ();