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 {  get set ; }

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 > ();
 
 
  本篇就介绍到这里,详细可下载本篇的源代码进行测试演习,欢迎大家拍砖~~~~~~~~




本文转自 beniao 51CTO博客,原文链接:http://blog.51cto.com/beniao/359781,如需转载请自行联系原作者

目录
相关文章
|
9月前
ant Table表格的一些常用的小功能以及常见的报错解决方法
ant Table表格的一些常用的小功能以及常见的报错解决方法
42 0
|
Windows
windows批量修改文件、文件夹名工具:Bulk Rename Utility批量改名演示
windows批量修改文件、文件夹名工具:Bulk Rename Utility批量改名演示
495 0
windows批量修改文件、文件夹名工具:Bulk Rename Utility批量改名演示
|
Java Go
将ABAP透明表的定义(元数据)解析出来导入到剪切板(clipboard)里
将ABAP透明表的定义(元数据)解析出来导入到剪切板(clipboard)里
将ABAP透明表的定义(元数据)解析出来导入到剪切板(clipboard)里
从加载DLL的中获取放置于Resources文件夹中资源字典的几种方法
原文:从加载DLL的中获取放置于Resources文件夹中资源字典的几种方法 主程序 为 Main_Test.exe 被加载的DLL 为 Load_Test.dll  此DLL 中 有一个 文件夹Resources文件夹有一个资源字典Graphics.
1282 0
|
XML 数据格式
【Tip】如何让引用的dll随附的xml注释文档、pdb调试库等文件不出现在项目输出目录中
原文:【Tip】如何让引用的dll随附的xml注释文档、pdb调试库等文件不出现在项目输出目录中 项目输出目录(bin/debug|release)中经常是这个样子: main.exemain.pdb a.dll a.xml b.dll b.pdb b.xml ... 其中xml是同名dll的注释文档,pdb是调试库。
914 0
|
数据格式 XML Android开发
EMF不能载入schema问题的解决
在EMF里可以用XML Schema定义模型,然后转换为genmodel模型,但我这里在生成genmodel向导的第四步按Load后会产生一个NullPointerException如下,导致无法继续: java.
1175 0

热门文章

最新文章