程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> MEF程序設計指南七

MEF程序設計指南七

編輯:關於.NET

使用目錄(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>();

本篇就介紹到這裡,詳細可下載本篇的源代碼進行測試演習,歡迎大家拍磚~~~~~~~~

文章出處:http://beniao.cnblogs.com/

本文配套源碼

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved