MEF程序設計指南七:使用目錄(Catalog)動態(tài)裝載xap與目錄篩選(Filtered Catalog)
如果不使用MEF進行托管擴展處理,只有通過WebClient進行程序包的下載、解析。實際上MEF的動態(tài)下載的底層實現(xiàn)一樣是使用的WebClient,然后利用AggregateCatalog進行動態(tài)組合,詳細可查看MEF的源代碼(路徑:Composition.Initialization\System\ComponentModel\Composition\Hosting\DeploymentCatalog.cs)。
在上一篇程序設計指南《MEF程序設計指南六:MEF中的目錄服務(DeploymentCatalog)》中介紹了MEF的目錄服務,并對MEF的目錄服務進行了接口封裝,其中有一個接口就是專門封裝的使用MEF的目錄進行.xap程序包的動態(tài)裝載的。
{
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的導入將接口導入到需要使用的地方,然后直接調用上面的方法即可實現(xiàn)對指定路徑的xap包的動態(tài)下載以及組合。
public IDeploymentService Service { get; set; }
private void button1_Click(object sender, System.Windows.RoutedEventArgs e)
{
this.Service.AddXap("MEFTraining.MefCatalogs.Parts.xap", null);
}
到這里我們還需要學習另外一個接口的使用,IPartImportsSatisfiedNotification接口就是一個當有新的部件進行裝配成功后的一個通知接口,可以準確的監(jiān)聽到MEF容器的組合,一旦有新的插件部件進行導入裝載到MEF容器中,此接口就會自動的得到通知。其內部就一個接口方法,詳細如下代碼塊:
{
}
在使用MEF目錄進行導出部件托管的時候,在某些需求下或許只需要其中的一個部件,這種情況可以通過遍歷部件集合得到。然而MEF也為此提供了一種解決方案,那就是使用目錄過濾篩選功能。MEF中的ComposablePartCatalog類和INotifyComposablePartCatalogChanged接口就是專門用來實現(xiàn)目錄篩選的,可以如下代碼段中演示的對目錄過濾的封裝。
{
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中的約定其篩選表達式應如下格式。
def => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) &&
((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) == CreationPolicy.NonShared);
MEF中提供了一個專門用于目錄過濾篩選的元數(shù)據(jù)特性PartMetadata,要進行目錄部件的篩選過濾就需要通過PartMetadata特性的標注,MEF容器才能進行正確的裝配。以一個簡單的實例演示,比如說有三個用戶控件(UserControl),分別進行導入和篩選過濾元數(shù)據(jù)的配置。
[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();
}
}
三個用戶控件的元數(shù)據(jù)名稱都為"UC",其值分別是AA、BB、CC,那么就可以通過下面代碼的方式實現(xiàn)對目錄中部件的篩選,下面是代碼塊演示了如何從目錄中篩選出元數(shù)據(jù)名稱為"UC",其值為"CC"的部件。
var catalog = new AssemblyCatalog(typeof(MainPage).Assembly);
//將目錄裝載進MEF組合容器
var parent = new CompositionContainer(catalog);
//通過元數(shù)據(jù)過濾篩選出元數(shù)據(jù)名稱為"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程序設計指南二:Silverlight中使用CompositionInitializer宿主MEF
MEF程序設計指南三:MEF中組合部件(Composable Parts)與契約(Contracts)的基本應用
MEF程序設計指南四:使用MEF聲明導出(Exports)與導入(Imports)
MEF程序設計指南五:遲延(Lazy)加載導出部件(Export Part)與元數(shù)據(jù)(Metadata)
MEF程序設計指南六:MEF中的目錄服務(DeploymentCatalog)
浙公網安備 33010602011771號