首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> 關於.NET

托管擴展性框架 (MEF) 深度實戰:構建可組合應用程式的完整指南

     編輯:關於.NET

.NET 4 引入 Managed Extensibility Framework (MEF),為「部署後仍可由第三方擴展」的可組合系統提供標準化基礎設施。本文系統闡述 MEF 核心概念、屬性化編程模型、進階特性(元數據、重新組合、穩定組合)、診斷工具及架構分層。

緣起:為何需要 MEF?

  • VS 2010 編輯器需延遲載入擴展以降低啟動開銷
  • 「Oslo」Intellipad 需支援 IronPython 插件
  • Acropolis 運行時需鬆耦合發現組件部件
  • 既有方案(EJB/OSGi/Spring/System.AddIn/IoC 容器)或過重、或雙向綁定過強,缺乏輕量級、單向、約定優於配置的通用方案

MEF 吸收諸家之長,專注解決「第三方可擴展性」核心痛點。

核心概念四要素

概念說明
部件可組合單元,提供/消費服務,來源不限(內部/外部)
導出部件提供的服務,以約定標識
導入部件需求的服務,以約定匹配
約定導出/導入的標識字串,默認從型別推導
組合容器實例化部件、匹配導出導入、構建物件圖的過程

屬性化編程模型:聲明式組合

基礎導出/導入


// 導出具體型別
[Export]
public partial class SalesOrderView : UserControl { ... }

// 導入屬性注入
[Export]
public class ViewFactory {
    [Import]
    public SalesOrderView OrderView { get; set; }
}

構造函數注入


[Export]
public class ViewFactory {
    [ImportingConstructor]
    public ViewFactory(SalesOrderView view) { ... }
}

啟動組合


public partial class App : Application {
    [Import] public ViewFactory ViewFactory { get; set; }

    void App_Startup(object sender, StartupEventArgs e) {
        var catalog = new DirectoryCatalog(@".\");
        var container = new CompositionContainer(catalog);
        container.ComposeParts(this);
    }
}

進階建模技巧

介面約定:解耦實作


public interface ISalesOrderView { }
[Export(typeof(ISalesOrderView))]
public partial class SalesOrderView : UserControl, ISalesOrderView { }

[Export]
public class ViewFactory {
    [Import] public ISalesOrderView OrderView { get; set; }
}

多導出:單部件支援多約定


[Export(typeof(ISalesOrderView))]
[Export(typeof(UserControl))]
public partial class SalesOrderView : UserControl, ISalesOrderView { }

約定程式集:第三方擴展的 SDK

建立 SalesOrderManager.Contracts 程式集,僅含介面定義,擴展開發者引用即可,不依賴宿主實作。

集合導入:開放式擴展點


public interface IView { }
[Export(typeof(IView))]
public partial class SalesOrderView : UserControl, IView { }

[Export]
public class ViewFactory {
    [ImportMany] public IEnumerable Views { get; set; }
}

新增視圖無需修改工廠,真正實現「對擴展開放,對修改關閉」。

建立策略控制:單例 vs 多例


[PartCreationPolicy(CreationPolicy.NonShared)]
[Export(typeof(ISalesOrderView))]
public partial class SalesOrderView : UserControl, ISalesOrderView { }
  • Shared (預設):容器內單例,所有導入共享
  • NonShared:每次導入創建新實例
  • Any:由導入端 RequiredCreationPolicy 決定

元數據:不實例化即可篩選

基礎元數據


[ExportMetadata("ViewType", "SalesOrder")]
[Export(typeof(IView))]
public partial class SalesOrderView : UserControl, IView { }

強型別自訂導出屬性(推薦)


[MetadataAttribute]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
public class ExportViewAttribute : ExportAttribute {
    public ExportViewAttribute() : base(typeof(IView)) { }
    public ViewTypes ViewType { get; set; }
}

public enum ViewTypes { SalesOrder }
public static class ViewMetadata { public const string ViewType = "ViewType"; }

[ExportView(ViewType = ViewTypes.SalesOrder)]
public partial class SalesOrderView : UserControl, IView { }

優勢:編譯期檢查、IntelliSense 發現、消除魔術字串、語義清晰。

延遲導入 + 元數據篩選


public interface IViewMetadata { ViewTypes ViewType { get; } }

[Export]
public class ViewFactory {
    [ImportMany] public IEnumerable> Views { get; set; }

    public IEnumerable GetViews(ViewTypes type) =>
        Views.Where(v => v.Metadata.ViewType == type).Select(v => v.Value);
}
  • Lazy<T, TMetadata>:Value 訪問時才實例化;Metadata 無需實例化即可讀取
  • LINQ 篩選後再 .Value 實例化,極致按需載入

重新組合:動態發現新部件


[ImportMany(AllowRecomposition = true)]
public IEnumerable> Views { get; set; }
  • 目錄變更(DirectoryCatalog.Refresh()、AggregateCatalog.Catalogs.Add())觸發自動更新
  • 集合類型決定更新語義:IEnumerable 整體替換;List/ICollection 增量 Clear/Add
  • 需注意執行緒安全

動態下載組件範例


var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(@".\"));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);

DownloadAssemblies(catalog); // 異步下載並 Add AssemblyCatalog

穩定組合與拒絕機制

  • 缺少必要導入 → 部件被**拒絕**,不拋異常,保持系統穩定
  • 多導出匹配單導入 → 同樣拒絕(除非標記預設導出)
  • 拒絕具有傳遞性:依賴被拒部件的部件也會被拒

診斷工具鏈

  1. IDE 輸出視窗: 即時追蹤拒絕訊息,含根因堆疊
  2. 監視視窗檢查: 觀察 catalog.Parts 可用導出與導入缺口
  3. MEFX 命令行工具: 靜態分析組件,預測拒絕
    
    mefx.exe /dir:bin\debug /rejected /verbose
        

架構三層次

層級命名空間職責
編程模型層System.ComponentModel.Composition屬性化/自訂模型,部件定義
宿主層System.ComponentModel.Composition.Hosting目錄、容器、組合引擎
基元層System.ComponentModel.Composition.PrimitivesComposablePartDefinition/ImportDefinition/ExportDefinition 等抽象

容器綁定基元而非屬性,支援非屬性化模型(如 DLR 動態語言)。

Silverlight 4 整合與展望

MEF 內建於 Silverlight 4,並引入額外 API 簡化 RIA 擴展開發,未來將回流 .NET Framework。擁抱 MEF,讓應用程式進入「無限可組合」的新世界。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved