MEF 編程指南(八):過濾目錄

當使用子容器的時候,基於特定的標準(Specific Criteria)過濾目錄是很必要的。好比,基於部件構造策略的過濾器是很常見的。下面的代碼片斷演示瞭如何構建的特殊途徑(Particular Approach):web

 
 var catalog = new AssemblyCatalog(typeof(Program).Assembly);
 var parent = new CompositionContainer(catalog);
 
 var filteredCat = new FilteredCatalog(catalog,
  def => def.Metadata.ContainsKey(CompositionConstants.PartCreationPolicyMetadataName) &&
  ((CreationPolicy)def.Metadata[CompositionConstants.PartCreationPolicyMetadataName]) == CreationPolicy.NonShared);
 var child = new CompositionContainer(filteredCat, parent);
 
 var root = child.GetExportedObject<Root>();
 child.Dispose();
 
若是 CreationPolicy 做爲標準選擇部件不能知足需求,你可能想到使用 [System.ComponentModel.Composition.PartMetadataAttribute] 替代。它容許爲部件附加元數據,所以能夠使用它構建過濾表達式。下面的示例就是 PartMetadata 特性的應用:
 
 [PartMetadata("scope", "webrequest"), Export]
 public class HomeController : Controller
 {
 }  
 
這容許你建立侷限於 Web 請求(邏輯)部件的子容器。請注意:範圍邊界取決於你的定義,換句話說,MEF 不知道 "webrequest"是什麼,因此你不得不建立一些基礎代碼來在每次Web 請求時建立/回收(Create/Dispose)容器。
 
 var catalog = new AssemblyCatalog(typeof(Program).Assembly);
 var parent = new CompositionContainer(catalog);
 
 var filteredCat = new FilteredCatalog(catalog,
  def => def.Metadata.ContainsKey("scope") &&
  def.Metadata["scope"].ToString() == "webrequest");
 var perRequest = new CompositionContainer(filteredCat, parent);
 
 var controller = perRequest.GetExportedObject<HomeController>();
 perRequest.Dispose();

 

注意:咱們並無提供 FilteredCatalog 類。下面演示瞭如何構建一個簡單的實現。
 
using System;
using System.ComponentModel.Composition.Primitives;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Linq.Expressions;
 
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 override IQueryable<ComposablePartDefinition> Parts
    {
        get
        {
            return _partsQuery;
        }
    }
 
    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;
        }
    }
}
 
原文地址:
相關文章
相關標籤/搜索