Managed Extensibility Framework (MEF) 是 .NET 4.0 內建的組合框架(System.ComponentModel.Composition),透過 Import/Export 屬性實現鬆耦合的元件發現與組合。本文示範如何在 WPF 應用中整合 MEF,實現客戶自訂表單/功能的動態載入,且無需重新編譯主程式。
AssemblyCatalog、DirectoryCatalog、AggregateCatalog)。CompositionContainer,負責解析匯入/匯出並建構物件圖。// 共用介面組件,主程式與擴充件皆參考
public interface IExtension
{
void ShowWindow();
}
[Export(typeof(IExtension))]
[ExportMetadata("MenuCaption", "客戶管理")] // 元資料:選單標題
public class CustomerExtension : IExtension
{
public void ShowWindow()
{
new CustomerWindow().Show();
}
}
編譯後的 DLL 放置於約定目錄(如 Extensions\)。
public partial class App : Application
{
private CompositionContainer _container;
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
if (Compose())
MainWindow = new MainWindow(); // 主視窗本身也是 Part
else
Shutdown();
}
protected override void OnExit(ExitEventArgs e)
{
_container?.Dispose(); // 釋放所有 IDisposable Part
base.OnExit(e);
}
private bool Compose()
{
try
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(Settings.Default.ExtensionPath));
catalog.Catalogs.Add(new AssemblyCatalog(typeof(App).Assembly)); // 包含主視窗自身
_container = new CompositionContainer(catalog);
var batch = new CompositionBatch();
batch.AddPart(this); // 讓 Application 自身參與組合
_container.Compose(batch);
return true;
}
catch (CompositionException ex)
{
MessageBox.Show($"組合失敗:{ex.Message}");
return false;
}
}
}
public partial class MainWindow : Window
{
// 強型別元資料,設計時智慧提示
[ImportMany]
public IEnumerable<Lazy<IExtension, IExtensionMetadata>> Extensions { get; set; }
private void Window_Loaded(object sender, RoutedEventArgs e)
{
foreach (var ext in Extensions)
{
var menuItem = new MenuItem { Header = ext.Metadata.MenuCaption };
menuItem.Click += (s, args) => ext.Value.ShowWindow();
ExtensionMenu.Items.Add(menuItem);
}
}
}
// 強型別元資料介面
public interface IExtensionMetadata
{
string MenuCaption { get; }
}
Shared(預設):單一實例共享所有匯入。NonShared:每次匯入建立新實例。[Export(typeof(IExtension)), PartCreationPolicy(CreationPolicy.NonShared)]
[Import(AllowDefault = true)] 允許找不到相符部件時不拋出異常(屬性為 null)。
| 特性 | MEF | MAF |
|---|---|---|
| 隔離層級 | 同一 AppDomain | 獨立 AppDomain/Process |
| 安全性 | 需信任擴充碼或配合 CAS | 天然隔離,適合不信任碼 |
| 版本控制 | 簡單,靠契約介面演進 | 內建版本協商機制 |
| 複雜度 | 低,屬性驅動 | 高,需 Pipeline/Adapter |
可結合兩者:MAF 提供隔離邊界,MEF 在隔離內部管理組合。
本文完整 VS 2010 方案(含主程式、擴充件專案、共用契約):
MEF WPF Extensibility Sample
MEF 以極簡單的屬性模型賦予應用程式強大的擴充能力,適合外掛架構、模組化 UI、動態策略載入等場景。掌握 Import/Export/Metadata/CreationPolicy 核心概念,即可構建高內聚、低耦合、易測試、易維護的企業級應用。