zoukankan      html  css  js  c++  java
  • MEF程序设计指南七:使用目录(Catalog)动态装载xap与目录筛选(Filtered Catalog)

      如果不使用MEF进行托管扩展处理,只有通过WebClient进行程序包的下载、解析。实际上MEF的动态下载的底层实现一样是使用的WebClient,然后利用AggregateCatalog进行动态组合,详细可查看MEF的源代码(路径:Composition.Initialization\System\ComponentModel\Composition\Hosting\DeploymentCatalog.cs)。

      在上一篇程序设计指南《MEF程序设计指南六:MEF中的目录服务(DeploymentCatalog)》中介绍了MEF的目录服务,并对MEF的目录服务进行了接口封装,其中有一个接口就是专门封装的使用MEF的目录进行.xap程序包的动态装载的。

    public void AddXap(string relativeUri, Action<AsyncCompletedEventArgs> completedAction)
    {
        DeploymentCatalog catalog;
        
    if (!_catalogs.TryGetValue(relativeUri, out catalog))
        {
            catalog 
    = new DeploymentCatalog(relativeUri);

            
    if (completedAction != null)
                catalog.DownloadCompleted 
    += (s, e) => completedAction(e);
            
    else
                catalog.DownloadCompleted 
    += DownloadCompleted;

            catalog.DownloadAsync();
            _catalogs[relativeUri] 
    = catalog;
            _aggregateCatalog.Catalogs.Add(catalog);

        }
    }

      其应用也非常简单,通过MEF的导入将接口导入到需要使用的地方,然后直接调用上面的方法即可实现对指定路径的xap包的动态下载以及组合。

    [Import]
    public IDeploymentService Service { getset; }

    private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
    {
        
    this.Service.AddXap("MEFTraining.MefCatalogs.Parts.xap"null);
    }

      到这里我们还需要学习另外一个接口的使用,IPartImportsSatisfiedNotification接口就是一个当有新的部件进行装配成功后的一个通知接口,可以准确的监听到MEF容器的组合,一旦有新的插件部件进行导入装载到MEF容器中,此接口就会自动的得到通知。其内部就一个接口方法,详细如下代码块:

    public void OnImportsSatisfied()
    {
                
    }

      在使用MEF目录进行导出部件托管的时候,在某些需求下或许只需要其中的一个部件,这种情况可以通过遍历部件集合得到。然而MEF也为此提供了一种解决方案,那就是使用目录过滤筛选功能。MEF中的ComposablePartCatalog类和INotifyComposablePartCatalogChanged接口就是专门用来实现目录筛选的,可以如下代码段中演示的对目录过滤的封装。

    public class FilteredCatalog : ComposablePartCatalog, INotifyComposablePartCatalogChanged
    {
        
    private readonly ComposablePartCatalog _inner;
        
    private readonly INotifyComposablePartCatalogChanged _innerNotifyChange;
        
    private readonly IQueryable<ComposablePartDefinition> _partsQuery;

        
    public FilteredCatalog(ComposablePartCatalog inner,
                            Expression
    <Func<ComposablePartDefinition, bool>> expression)
        {
            _inner 
    = inner;
            _innerNotifyChange 
    = inner as INotifyComposablePartCatalogChanged;
            _partsQuery 
    = inner.Parts.Where(expression);
        }

        
    public event EventHandler<ComposablePartCatalogChangeEventArgs> Changed
        {
            add
            {
                
    if (_innerNotifyChange != null)
                    _innerNotifyChange.Changed 
    += value;
            }
            remove
            {
                
    if (_innerNotifyChange != null)
                    _innerNotifyChange.Changed 
    -= value;
            }

        }

        
    public event EventHandler<ComposablePartCatalogChangeEventArgs> Changing
        {
            add
            {
                
    if (_innerNotifyChange != null)
                    _innerNotifyChange.Changing 
    += value;
            }
            remove
            {
                
    if (_innerNotifyChange != null)
                    _innerNotifyChange.Changing 
    -= value;
            }

        }

        
    public override System.Linq.IQueryable<ComposablePartDefinition> Parts
        {
            
    get
            {
                
    return _partsQuery;
            }
        }
    }

       通过上面的封装,使用目录过滤功能之需要传入正确的筛选表达式就可以了,按照MEF中的约定其筛选表达式应如下格式。

    var filteredCat = new FilteredCatalog(catalog,
        def 
    => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) &&
            ((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) 
    == CreationPolicy.NonShared);

      MEF中提供了一个专门用于目录过滤筛选的元数据特性PartMetadata,要进行目录部件的筛选过滤就需要通过PartMetadata特性的标注,MEF容器才能进行正确的装配。以一个简单的实例演示,比如说有三个用户控件(UserControl),分别进行导入和筛选过滤元数据的配置。

    [PartMetadata("UC""AA")]
    [Export(
    typeof(UserControl))]
    public partial class AA : UserControl
    {
        
    public AA()
        {
            InitializeComponent();
        }
    }

    [PartMetadata(
    "UC""BB")]
    [Export(
    typeof(UserControl))]
    public partial class BB : UserControl
    {
        
    public BB()
        {
            InitializeComponent();
        }
    }

    [PartMetadata(
    "UC""CC")]
    [Export(
    typeof(UserControl))]
    public partial class CC : UserControl
    {
        
    public CC()
        {
            InitializeComponent();
        }
    }

      三个用户控件的元数据名称都为"UC",其值分别是AA、BB、CC,那么就可以通过下面代码的方式实现对目录中部件的筛选,下面是代码块演示了如何从目录中筛选出元数据名称为"UC",其值为"CC"的部件。

    //获取当前应用程序目录
    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 perRequest 
    = new CompositionContainer(filteredCat, parent);
    var control 
    = perRequest.GetExportedValue<UserControl>();

      本篇就介绍到这里,详细可下载本篇的源代码进行测试演习,欢迎大家拍砖~~~~~~~~

      

      本篇参考于:Filtered Catalogs  Paritioning applications across multiple XAPs

      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)

    相关说明

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

    作      者:Beniao

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

  • 相关阅读:
    求1+2+3+...+n
    孩子们的游戏(圆圈中最后剩下的数) 约瑟夫环
    扑克牌顺子
    翻转单词顺序列
    左旋转字符串
    和为S的两个数字
    和为S的连续正数序列
    CocoaPods 更新
    UITextView 动态高度计算(iOS7版)
    Mac 把图片反色
  • 原文地址:https://www.cnblogs.com/beniao/p/1782622.html
Copyright © 2011-2022 走看看