首页 > 其他分享 >[MEF]第05篇 MEF的目录(Catalog)筛选

[MEF]第05篇 MEF的目录(Catalog)筛选

时间:2023-07-02 11:04:49浏览次数:55  
标签:MEF 05 部件 NotifyComposablePartCatalogChanged Catalog 过滤 ComposablePartCatalog 目录



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

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


二、自定义部件目录类Catalog

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

public class FilteredCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged
{
    #region Private Fields


    private readonly ComposablePartCatalog m_ComposablePartCatalog;
    private readonly INotifyComposablePartCatalogChanged m_NotifyComposablePartCatalogChanged;
    private readonly IQueryable<ComposablePartDefinition> m_Parts;


    #endregion


    #region Constructors


    /// <summary>
    /// 默认构造函数。
    /// </summary>
    /// <param name="composablePartCatalog">包含了所有导出部件的目录Catalog。</param>
    /// <param name="expression">筛选条件表达式。</param>
    public FilteredCatalog(ComposablePartCatalog composablePartCatalog, Expression<Func<ComposablePartDefinition, bool>> expression)
    {
        m_ComposablePartCatalog = composablePartCatalog;
        m_NotifyComposablePartCatalogChanged = composablePartCatalog as INotifyComposablePartCatalogChanged;
        m_Parts = composablePartCatalog.Parts.Where(expression);
    }


    #endregion


    #region INotifyComposablePartCatalogChanged


    /// <summary>
    /// 部件目录Catalog已经改变后触发的事件。
    /// </summary>
    public event EventHandler<ComposablePartCatalogChangeEventArgs> Changed
    {
        add
        {
            if (m_NotifyComposablePartCatalogChanged != null)
            {
                m_NotifyComposablePartCatalogChanged.Changed += value;
            }
        }
        remove
        {
            if (m_NotifyComposablePartCatalogChanged != null)
            {
                m_NotifyComposablePartCatalogChanged.Changed -= value;
            }
        }
    }


    /// <summary>
    /// 部件目录Catalog正在发生改变时触发的事件。
    /// </summary>
    public event EventHandler<ComposablePartCatalogChangeEventArgs> Changing
    {
        add
        {
            if (m_NotifyComposablePartCatalogChanged != null)
            {
                m_NotifyComposablePartCatalogChanged.Changing += value;
            }
        }
        remove
        {
            if (m_NotifyComposablePartCatalogChanged != null)
            {
                m_NotifyComposablePartCatalogChanged.Changing -= value;
            }
        }
    }


    #endregion


    #region ComposablePartCatalog


    /// <summary>
    /// 获取目录中包含的部件定义。经过构造函数中的表达式过滤后,已经是传入目录Catalog对象中的一部分导出部件了。
    /// </summary>
    public override IQueryable<ComposablePartDefinition> Parts
    {
        get { return m_Parts; }
    }


    #endregion
}

上述代码中概括来说包含如下几点内容:


1、构造函数传递了基础目录Catalog对象,这个目录对象可能包含了很多的导出部件,我们要实现的目录过滤类FilteredCatalog就是基于这个目录进行过滤的,它是个全集,而FilteredCatalog是它的子集。另外一个参数是过滤表达式,过滤条件由调用者来编写,至于内部过滤办法实际还是LINQ提供的Where()方法。


2、对于接口INotifyComposablePartCatalogChanged的实现,实际上是和基础目录Catalog对象的事件关联在一起,即当基础目录对象发生改变时,目录过滤类FilteredCatalog也将会收到相应的通知。


3、重写了基类ComposablePartCatalog的Parts集合属性,该属性返回的就是该目录中包含部件定义,凡是在目录中需要被暴露的部件定义都是通过该集合返回的。因此,上述代码中将过滤后的部件定义通过该属性返回。



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



三、使用自定义目录类Catalog


如下代码所示:


// 获取所需的部件。
DirectoryCatalog catalog = new DirectoryCatalog("controls");
CompositionContainer container = new CompositionContainer(catalog);


// 过滤Catalog,生成子组合容器。
FilteredCatalog filteredCatalog = new FilteredCatalog(catalog,
    o=>o.Metadata.ContainsKey("UC") && o.Metadata["UC"].ToString() == "BB");
CompositionContainer filteredContainer = new CompositionContainer(filteredCatalog, container);


UserControl userControl = filteredContainer.GetExportedValue<UserControl>();
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)》,







标签:MEF,05,部件,NotifyComposablePartCatalogChanged,Catalog,过滤,ComposablePartCatalog,目录
From: https://blog.51cto.com/u_3319687/6603730

相关文章

  • [MEF]第01篇 MEF使用入门
    一、演示概述此演示初步介绍了MEF的基本使用,包括对MEF中的Export、Import和Catalog做了初步的介绍,并通过一个具体的Demo来展示MEF是如何实现高内聚、低耦合和高扩展性的软件架构。演示中,针对于IBookService接口,有3个不同版本的实现,分别是ComputerBookServiceImp、HistoryBookSer......
  • 05 CRUD 套餐 + 实战内容(后续补充 ing)
    新增套餐预准备代码实现复制资料下的SetmealDish类到entity下,复制SetmealDto到dto下。添加套餐菜品/查询菜品数据DishController下:/***根据条件查询对应的菜品数据*@paramdish*@return*/@GetMapping("/list")publicR<Li......
  • 【题解】#105. 「USACO1.3」Ski Course Design 题解(2023-07-01更新)
    #105.「USACO1.3」SkiCourseDesign题解题目传送门欢迎大家指出错误并联系这个蒟蒻更新日志2023-02-0117:20文章完成2023-02-0316:09文章审核通过2023-02-0422:15修改了注释2023-05-1621:44修改了$\LaTeX$2023-07-0115:59修改了代码题目知识点模拟+搜索......
  • web自动化测试入门篇05——元素定位的配置管理
      ......
  • IIS上Put操作出现HTTP Error 405.0 - Method Not Allowed 解决方法
    WebDAV是超文本传输协议(HTTP)的一组扩展,为Internet上计算机之间的编辑和文件管理提供了标准.利用这个协议用户可以通过Web进行远程的基本文件操作,如拷贝、移动、删除等。在IIS7.0中,WebDAV是作为独立扩展模块,需要单独进行下载,而IIS7.5以及以上版本中......
  • AP8505高压同步整流 5V150mA非隔离电源ic
    深圳市三佛科技有限公司AP8505高压同步整流5V150mA非隔离电源icAP8505基于高压同步整流架构,集成PFM控制器以及500V高可靠性MOSFET,用于外部元器件极精简的小功率非隔离开关电源。AP8505无线门铃芯片内置500V高压启动,实现系统快速启动、超低待机功能。5V非隔离无线门铃芯片AP8505提......
  • Doris 1.2.0 JDBC外表 及 Mutil Catalog
    环境doris需要版本1.2以上jar包根据不同的数据源需要不同的jar包https://mvnrepository.com/a.MySQLmysql-connector-java-5.1.47.jarb.PostgreSQLpostgresql-42.5.1.jarc.Oracleojdbc8.jard.Clickhouseclickhouse-jdbc-0.3.2-patch11......
  • [MEF]第04篇 MEF的多部件导入(ImportMany)和目录服务
    一、演示概述此演示介绍了MEF如何使用ImportMany特性同时导入多个与相同约束相匹配的导出部件,并且介绍了目录服务(Catalog),该服务告知MEF框架可以在什么地方去搜寻与指定约束匹配的导出部件,即导出部件位于什么地方。相关下载(屏幕录像、代码):http://yunpan.cn/cVdN5JHeQrJgI ......
  • 光脚丫思考Vue3与实战:第05章 计算属性和侦听器 第03节 计算属性的其他玩法
    下面是本文的屏幕录像的在线视频:温馨提示:1、视频下载:线上视频被压缩处理,可以下载高清版本:链接:https://pan.baidu.com/s/1h600_BRR9O2Lr87zVQNgEw 提取码:dgpu 2、示例代码:https://pan.baidu.com/s/1rCqbY_j35FcRWRZbuOfHqg 提取码:79kh 下图是文章大纲:一、概述本篇文章介绍了V......
  • 光脚丫学LINQ(005):数据表之间的联接查询
      视频演示:http://u.115.com/file/f29a440f67 联接运算创建数据源中没有显式建模的序列之间的关联。例如,您可以执行联接来查找符合以下条件的所有客户:位于巴黎,且从位于伦敦的供应商处订购产品。在LINQ中,join子句始终针对对象集合而非直接针对数据库表运行。在LINQ中,您不必......