zoukankan      html  css  js  c++  java
  • [MEF]第05篇 MEF的目录(Catalog)筛选

    一、演示概述
    本示例演示如何使用MEF提供的目录(Catalog)的扩展机制实现可过滤导出部件的自定义目录类。主要是通过继承ComposablePartCatalog基类,并实现接口INotifyComposablePartCatalogChanged来完成的。
    相关下载(屏幕录像)http://yunpan.cn/cVkvuUNfuDtTX  访问密码 567d
    温馨提示:如果屏幕录像和代码不能正常下载,可站内留言,或发邮件到524130780@QQ.COM

    欢迎有兴趣研究.NET相关技术的网友加QQ群:18507443


    二、自定义部件目录类Catalog

    在MEF中,除了可以使用自身提供的注入AggregateCatalog、AssemblyCatalog、DirectoryCatalog这样的目录类以外,也可以自己定义目录类。
    自定义目录类需要继承自ComposablePartCatalog类,并实现接口INotifyComposablePartCatalogChanged即可。如下面所示的代码:

    [csharp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. public class FilteredCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged  
    2. {  
    3.     #region Private Fields  
    4.   
    5.   
    6.     private readonly ComposablePartCatalog m_ComposablePartCatalog;  
    7.     private readonly INotifyComposablePartCatalogChanged m_NotifyComposablePartCatalogChanged;  
    8.     private readonly IQueryable<ComposablePartDefinition> m_Parts;  
    9.  
    10.  
    11.     #endregion  
    12.  
    13.  
    14.     #region Constructors  
    15.   
    16.   
    17.     /// <summary>  
    18.     /// 默认构造函数。  
    19.     /// </summary>  
    20.     /// <param name="composablePartCatalog">包含了所有导出部件的目录Catalog。</param>  
    21.     /// <param name="expression">筛选条件表达式。</param>  
    22.     public FilteredCatalog(ComposablePartCatalog composablePartCatalog, Expression<Func<ComposablePartDefinition, bool>> expression)  
    23.     {  
    24.         m_ComposablePartCatalog = composablePartCatalog;  
    25.         m_NotifyComposablePartCatalogChanged = composablePartCatalog as INotifyComposablePartCatalogChanged;  
    26.         m_Parts = composablePartCatalog.Parts.Where(expression);  
    27.     }  
    28.  
    29.  
    30.     #endregion  
    31.  
    32.  
    33.     #region INotifyComposablePartCatalogChanged  
    34.   
    35.   
    36.     /// <summary>  
    37.     /// 部件目录Catalog已经改变后触发的事件。  
    38.     /// </summary>  
    39.     public event EventHandler<ComposablePartCatalogChangeEventArgs> Changed  
    40.     {  
    41.         add  
    42.         {  
    43.             if (m_NotifyComposablePartCatalogChanged != null)  
    44.             {  
    45.                 m_NotifyComposablePartCatalogChanged.Changed += value;  
    46.             }  
    47.         }  
    48.         remove  
    49.         {  
    50.             if (m_NotifyComposablePartCatalogChanged != null)  
    51.             {  
    52.                 m_NotifyComposablePartCatalogChanged.Changed -= value;  
    53.             }  
    54.         }  
    55.     }  
    56.   
    57.   
    58.     /// <summary>  
    59.     /// 部件目录Catalog正在发生改变时触发的事件。  
    60.     /// </summary>  
    61.     public event EventHandler<ComposablePartCatalogChangeEventArgs> Changing  
    62.     {  
    63.         add  
    64.         {  
    65.             if (m_NotifyComposablePartCatalogChanged != null)  
    66.             {  
    67.                 m_NotifyComposablePartCatalogChanged.Changing += value;  
    68.             }  
    69.         }  
    70.         remove  
    71.         {  
    72.             if (m_NotifyComposablePartCatalogChanged != null)  
    73.             {  
    74.                 m_NotifyComposablePartCatalogChanged.Changing -= value;  
    75.             }  
    76.         }  
    77.     }  
    78.  
    79.  
    80.     #endregion  
    81.  
    82.  
    83.     #region ComposablePartCatalog  
    84.   
    85.   
    86.     /// <summary>  
    87.     /// 获取目录中包含的部件定义。经过构造函数中的表达式过滤后,已经是传入目录Catalog对象中的一部分导出部件了。  
    88.     /// </summary>  
    89.     public override IQueryable<ComposablePartDefinition> Parts  
    90.     {  
    91.         get { return m_Parts; }  
    92.     }  
    93.  
    94.  
    95.     #endregion  
    96. }  

    上述代码中概括来说包含如下几点内容:
    1、构造函数传递了基础目录Catalog对象,这个目录对象可能包含了很多的导出部件,我们要实现的目录过滤类FilteredCatalog就是基于这个目录进行过滤的,它是个全集,而FilteredCatalog是它的子集。另外一个参数是过滤表达式,过滤条件由调用者来编写,至于内部过滤办法实际还是LINQ提供的Where()方法。
    2、对于接口INotifyComposablePartCatalogChanged的实现,实际上是和基础目录Catalog对象的事件关联在一起,即当基础目录对象发生改变时,目录过滤类FilteredCatalog也将会收到相应的通知。
    3、重写了基类ComposablePartCatalog的Parts集合属性,该属性返回的就是该目录中包含部件定义,凡是在目录中需要被暴露的部件定义都是通过该集合返回的。因此,上述代码中将过滤后的部件定义通过该属性返回。

    定义好了过滤类,接下来就是如何使用它了。

    三、使用自定义目录类Catalog
    如下代码所示:

    [csharp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. // 获取所需的部件。  
    2. DirectoryCatalog catalog = new DirectoryCatalog("controls");  
    3. CompositionContainer container = new CompositionContainer(catalog);  
    4.   
    5.   
    6. // 过滤Catalog,生成子组合容器。  
    7. FilteredCatalog filteredCatalog = new FilteredCatalog(catalog,  
    8.     o=>o.Metadata.ContainsKey("UC") && o.Metadata["UC"].ToString() == "BB");  
    9. CompositionContainer filteredContainer = new CompositionContainer(filteredCatalog, container);  
    10.   
    11.   
    12. UserControl userControl = filteredContainer.GetExportedValue<UserControl>();  
    13. this.MainContentControl.Content = userControl;  

    首先通过DirectoryCatalog类获取到应用程序根目录下controls子文件夹中的所有部件定义,并以此生成顶级组合容器container(类型为CompositionContainer)。
    然后使用自定义目录过滤类FilteredCatalog对DirectoryCatalog目录中的部件定义进行过滤,并生成子组合容器filteredContainer(类型为CompositionContainer)。
    最后通过组合容器的GetExportedValue<T>()方法获取指定协议类型的导出部件。需要说明的是,如果组合容器中没有对应协议类型的导出部件则会引发异常。

    可通过如下地址获取完整的示例代码和屏幕录像文件。

    四、相关资源
    1、MSDN官方资料:http://msdn.microsoft.com/zh-cn/library/dd460648(v=vs.110).aspx

    2、参考了微软MVP Bēniaǒ的文章《MEF程序设计指南七:使用目录(Catalog)动态装载xap与目录筛选(Filtered Catalog)》,访问地址:http://www.cnblogs.com/beniao/archive/2010/07/26/1782622.html

  • 相关阅读:
    华为机试练习(一)
    LM拟合算法
    5.1 模块化程序设计
    第3周 运算的流程控制
    KEGG数据库介绍
    topGO
    GO.db
    Bioconductor应用领域之基因芯片
    org.Hs.eg.db包简介(转换NCBI、ensemble等数据库中基因ID,symbol等之间的转换)
    Bioconductor的历史
  • 原文地址:https://www.cnblogs.com/ExMan/p/5487218.html
Copyright © 2011-2022 走看看