Managed Extensibility Framework (MEF) 讓開發者能在 .NET 應用程式中提供掛鉤,供使用者與第三方擴充。可視為通用應用程式擴充工具。MEF 支援動態創建擴充,無需修改應用程式,亦無需擴充內容相關知識,確保編譯時零耦合,運行時即可擴充、無需重新編譯。MEF 還能在載入擴充前檢視元數據,採用更快速的方式。
主要實現方式:在應用程式擴充點加 Import 屬性,擴充加 Export 屬性。Export 為供應者提供價值,Import 為消費者消費價值。
目標: 定義組件可擴充選項、執行條件綁定與組件創建、運行時導入擴充組件。
需求: Visual Studio 2010、.NET Framework 4。
以管理員權限運行命令列腳本,執行 CheckDependencies.cmd 驗證先決條件並安裝代碼片段。解決方案檔位於 %TrainingKitInstallFolder%\Labs\IntroToMEF\Source\Ex01-DynamicallyAddModules\begin\C#。
用戶初始安裝特定模組,後續需添加更多。MEF 可配置應用程式監控已知目錄,自動載入該目錄下的模組組件,無需顯式引用。
MainForm.cs 代碼視圖。using System.ComponentModel.Composition; using System.ComponentModel.Composition.Hosting;[ImportMany]
public Lazy<IMainFormContract, IDictionary<string, object>>[] ImportedMainFormContracts { get; set; }
CompositionContainer:private CompositionContainer _container;private CompositionContainer GetContainerFromDirectory() {
var catalog = new AggregateCatalog();
var thisAssembly = new AssemblyCatalog(Assembly.GetExecutingAssembly());
catalog.Catalogs.Add(thisAssembly);
catalog.Catalogs.Add(new DirectoryCatalog(_extensionDir));
return new CompositionContainer(catalog);
}
Compose 方法解析導入導出:
private bool Compose() {
_container = GetContainerFromDirectory();
try { _container.ComposeParts(this); }
catch (CompositionException ex) { MessageBox.Show(ex.ToString()); return false; }
return true;
}
Compose,失敗則關閉窗體。MefEmployeeModule 專案添加 System.ComponentModel.Composition 參考。EmployeeMaintenance.cs 頂部添加 using System.ComponentModel.Composition;。[Export(typeof(IMainFormContract))]
[ExportMetadata("Name", "Employee Pane")]
[ExportMetadata("MenuText", "&Employees")]
public partial class EmployeeMaintenance : Form, IMainFormContract
IMainFormContract 介面屬性 MenuItemText 與 SubFormTitle。MainForm_Load 事件中遍歷導入集合,根據元數據動態添加選單項並掛鉤點擊事件。LaunchModule_Click 透過元數據匹配啟動對應表單。ExtModules 目錄。MefLabMain 為啟動專案,按 F5 運行。初始 Modules 選單為空。擴充 EmployeeMaintenance 窗體,動態載入命令按鈕 (Add/Delete Employee)。應用程式無論有無擴充皆能正常工作,雙方鬆散耦合,透過 Interface 契約支援。
修改 AddEmployeeButton.cs 與 DeleteEmployeeButton.cs,加上 [Export(typeof(ICmdButtonInfo))]。
設計模式下拖放 Panel 至 DataGridView 下方,命名為 ButtonsPanel,寬度匹配 DataGridView。
EmployeeMaintenance 類頂部定義導入集合:
[ImportMany]
public Lazy<ICmdButtonInfo>[] ImportedButtons { get; set; }
CreateButtons 方法遍歷集合,將按鈕加入 Panel,設置位置與 CompanyInfo。EmployeeMaintenance_Load 調用 CreateButtons。empDataGridView_SelectionChanged 更新 CompanyInfo.SelectedEmployee,並在設計器綁定事件。本實驗使用 MEF 為應用程式添加擴充點並構建擴充插入。MEF 讓您以導出屬性載入外部組件、無需顯式引用、運行時動態擴充。您學習了 Import/Export 交互、透過介面契約指定導出組件。