.NET 4 引入 Managed Extensibility Framework (MEF),為「部署後仍可由第三方擴展」的可組合系統提供標準化基礎設施。本文系統闡述 MEF 核心概念、屬性化編程模型、進階特性(元數據、重新組合、穩定組合)、診斷工具及架構分層。
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 { }
建立 SalesOrderManager.Contracts 程式集,僅含介面定義,擴展開發者引用即可,不依賴宿主實作。
public interface IView { }
[Export(typeof(IView))]
public partial class SalesOrderView : UserControl, IView { }
[Export]
public class ViewFactory {
[ImportMany] public IEnumerable Views { get; set; }
}
新增視圖無需修改工廠,真正實現「對擴展開放,對修改關閉」。
[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 無需實例化即可讀取.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
catalog.Parts 可用導出與導入缺口
mefx.exe /dir:bin\debug /rejected /verbose
| 層級 | 命名空間 | 職責 |
|---|---|---|
| 編程模型層 | System.ComponentModel.Composition | 屬性化/自訂模型,部件定義 |
| 宿主層 | System.ComponentModel.Composition.Hosting | 目錄、容器、組合引擎 |
| 基元層 | System.ComponentModel.Composition.Primitives | ComposablePartDefinition/ImportDefinition/ExportDefinition 等抽象 |
容器綁定基元而非屬性,支援非屬性化模型(如 DLR 動態語言)。
MEF 內建於 Silverlight 4,並引入額外 API 簡化 RIA 擴展開發,未來將回流 .NET Framework。擁抱 MEF,讓應用程式進入「無限可組合」的新世界。