随笔- 292  评论- 3614  文章- 47 

MEF程序设计指南八:部件生命周期(Parts Lifetime)托管

  MEF中的每一个可进行动态装配的导出部件都是具有生命周期的,在没有特别需求的情况下一般都没有对生命周期进行管理,而实际上MEF已为每一个部件进行了默认的生命周期管理,MEF的生命周期分为三种:Any、Shared及NonShared,被定义在System.ComponentModel.Composition.CreationPolicy枚举对象中。
namespace System.ComponentModel.Composition
{
    
public enum CreationPolicy
    {
         Any 
= 0,
         Shared 
= 1,
         NonShared 
= 2,
    }
}

 

  Any表示可共享或不共享,部件的实例用MEF容器根据不同的请求需求自动控制;Shared表示共享部件,既Shared类型的插件部件可以在多个MEF组合容器中共用;其次是NonShared类型,表示不共享部件实例,每当有新的请求就会创建一个新的对象实例。在MEF中,通过PartCreationPolicyAttribute特性实现对部件的生命周期配置。

public interface IBookService
{
    
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类型的生命周期托管类型对不同的对象进行导出部件配置。接下来通过导入部件并加入生命周期托管筛选,详细应用如下代码块所示:

public partial class MainPage : UserControl
{
    [ImportMany(RequiredCreationPolicy 
= CreationPolicy.Shared)]
    
public List<IBookService> Service { getset; }

    
public MainPage()
    {
        InitializeComponent();

        CompositionInitializer.SatisfyImports(
this);
        
//得到成功装配的部件总数为2,因为Any类型是可以共存于多个MEF容器的。
        int count = Service.Count;
    }
}

 

  表面上看去和上一篇指南中介绍的部件的筛选过滤功能非常相似,不同是的过滤筛选是通过自定义筛选策略实现,而这里是通过MEF生命周期范围托管来实现的。在实际的项目开发中需根据不同的应用场景确定具体的技术实现方案。

 

  除了容器部件的生命周期托管,我们也得考虑部件容器自身的生命周期,容器什么时候释放资源,时候时候释放其内部部件的资源占用等。为了提高系统的整体性能,MEF建议将每一个可导入部件实现IDisposable 接口,用于资源的占用处理,如果部件从MEF容器中移除那么所对应占用的资源也会自动的清理。这里需要注意一点,就是当组合容器被释放掉后迟延加载的操作就不能再继续工作了,会抛出System.ObjectDisposedException异常。

 

      

  如上图所示,MEF的容器是具有层次结构的,最高层级容器为程序直接应用级容器,可以通过以下的代码获取到。

 

var catalog = new AssemblyCatalog(typeof(MainPage).Assembly);
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>();

 

 

MEF官方网站:http://mef.codeplex.com/

  推荐指南:MEF程序设计指南一:在应用程序中宿主MEF

         MEF程序设计指南二:Silverlight中使用CompositionInitializer宿主MEF

         MEF程序设计指南三:MEF中组合部件(Composable Parts)与契约(Contracts)的基本应用

       MEF程序设计指南四:使用MEF声明导出(Exports)与导入(Imports)

            MEF程序设计指南五:迟延(Lazy)加载导出部件(Export Part)与元数据(Metadata)

        MEF程序设计指南六:MEF中的目录服务(DeploymentCatalog)

                   MEF程序设计指南七:使用目录(Catalog)动态装载xap与目录筛选(Filtered Catalog)

 

相关说明

 本文属学习笔记文章,愿与有志者共同学习交流。欢迎转载,但请在明显地位标记本文的原文连接。  

作      者:Beniao

文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

 

posted on 2010-07-28 23:14 Bēniaǒ 阅读(...) 评论(...) 编辑 收藏