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

受控擴展架構(MEF)實戰:構建可擴充的 WPF 應用程式

     編輯:關於.NET

Managed Extensibility Framework (MEF) 是 .NET 4.0 內建的組合框架(System.ComponentModel.Composition),透過 Import/Export 屬性實現鬆耦合的元件發現與組合。本文示範如何在 WPF 應用中整合 MEF,實現客戶自訂表單/功能的動態載入,且無需重新編譯主程式。

一、核心概念

  • Part(部件):任何可被 MEF 管理的類別,可同時扮演匯出者與匯入者。
  • Contract(契約):通常為介面,定義部件互動協議。
  • Catalog(目錄):部件發現來源(AssemblyCatalog、DirectoryCatalog、AggregateCatalog)。
  • Container(容器):CompositionContainer,負責解析匯入/匯出並建構物件圖。

二、定義擴充契約

// 共用介面組件,主程式與擴充件皆參考
public interface IExtension
{
    void ShowWindow();
}

三、撰寫擴充件

[Export(typeof(IExtension))]
[ExportMetadata("MenuCaption", "客戶管理")] // 元資料:選單標題
public class CustomerExtension : IExtension
{
    public void ShowWindow()
    {
        new CustomerWindow().Show();
    }
}

編譯後的 DLL 放置於約定目錄(如 Extensions\)。

四、主程式整合 MEF

1. Application 層級管理容器生命週期

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;
        }
    }
}

2. 主視窗匯入擴充件並動態建構選單


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 vs MAF (System.AddIn)

特性MEFMAF
隔離層級同一 AppDomain獨立 AppDomain/Process
安全性需信任擴充碼或配合 CAS天然隔離,適合不信任碼
版本控制簡單,靠契約介面演進內建版本協商機制
複雜度低,屬性驅動高,需 Pipeline/Adapter

可結合兩者:MAF 提供隔離邊界,MEF 在隔離內部管理組合。

六、完整範例下載

本文完整 VS 2010 方案(含主程式、擴充件專案、共用契約):
MEF WPF Extensibility Sample

結語

MEF 以極簡單的屬性模型賦予應用程式強大的擴充能力,適合外掛架構、模組化 UI、動態策略載入等場景。掌握 Import/Export/Metadata/CreationPolicy 核心概念,即可構建高內聚、低耦合、易測試、易維護的企業級應用。

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