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

MEF 實戰:輕鬆打造可擴展的 .NET 應用程式

     編輯:關於.NET

前言

Managed Extensibility Framework(MEF)是 .NET 平台上一套強大的擴充性管理框架,整合了依賴注入(DI)與 Duck Typing 等特性。它讓開發人員能以最小代碼變動擴充應用程式:開發階段定義擴充點,擴充人員即可透過這些點與主程式互動,且雙方不產生直接依賴,甚至可跨多個專案共用擴充元件。

基本依賴注入範例

首先看一個簡單的主程式,直接輸出字串:

// Author: TerryLee 2008.8.30
// URL: https://www.cnblogs.com/Terrylee
static void Main(string[] args)
{
    Console.WriteLine("This is a simple string.");
}

若此字串未來可能變動、來源不固定,便可視為一個擴充點。使用 MEF 重構為「提供者」與「消費者」兩部分:

1. 定義字串提供者(輸出端)

// Author: TerryLee 2008.8.30
// URL: https://www.cnblogs.com/Terrylee
public class WeekStringProvider
{
    [Export("Caption")]
    public String OutputTitle
    {
        get { return "星期六"; }
    }
}

[Export("Caption")] 標記此屬性為可被發現的輸出,契約名稱為 "Caption"。同一類別可定義多個 Export,也可改用型別作為契約。

2. 定義消費者(輸入端)

// Author: TerryLee 2008.8.30
// URL: https://www.cnblogs.com/Terrylee
public class Client
{
    [Import("Caption")]
    public String OutputTitle { get; set; }
}

[Import("Caption")] 聲明需要契約名稱為 "Caption" 的字串。

3. 組合與執行

// Author: TerryLee 2008.8.30
// URL: https://www.cnblogs.com/Terrylee
static void Main(string[] args)
{
    Client client = new Client();
    CompositionContainer container = new CompositionContainer();
    container.AddComponent<Client>(client);
    container.AddComponent<WeekStringProvider>(new WeekStringProvider());
    container.Bind();
    Console.WriteLine(client.OutputTitle);
}

切換擴充實作

只需替換註冊的元件,即可改變行為,無須修改主程式邏輯:

public class DateStringProvider
{
    [Export("Caption")]
    public String OutputTitle
    {
        get { return DateTime.Now.ToLongDateString(); }
    }
}
static void Main(string[] args)
{
    Client client = new Client();
    CompositionContainer container = new CompositionContainer();
    container.AddComponent<Client>(client);
    container.AddComponent<DateStringProvider>(new DateStringProvider());
    container.Bind();
    Console.WriteLine(client.OutputTitle);
}

型別契約與 Duck Typing

除了字串契約,MEF 支援型別契約。定義介面 IStringProvider,提供者實作介面並標記 [Export(typeof(IStringProvider))],消費者以 [Import(typeof(IStringProvider))] 引入,效果相同。

Duck Typing 更進一步:輸入端要求 ICalculator,擴充端可實作不同介面 IMyCalculator,只要雙方以相同 ContractType 標記,即可自動匹配。這意味著擴充元件完全不需參考主程式組件,實現真正的鬆散耦合。

[ContractType("TerryLeeCalculatro")]
public interface ICalculator { int Execute(int x, int y); }

[Export(typeof(ICalculator))]
public class SubCalculator : ICalculator { public int Execute(int x, int y) => x - y; }

[ContractType("TerryLeeCalculatro")]
public interface IMyCalculator { int Execute(int x, int y); }

[Export(typeof(IMyCalculator))]
public class AddCalculator : IMyCalculator { public int Execute(int x, int y) => x + y; }

Plug-In 機制:目錄監視自動發現

透過 DirectoryWatchingComponentCatalog 監視指定資料夾(如 Extensions),主程式無須硬編碼註冊,只要將擴充組件放入目錄即自動載入:

static void Main(string[] args)
{
    User user = new User();
    DirectoryWatchingComponentCatalog catalog = new DirectoryWatchingComponentCatalog();
    catalog.AddDirectory(@"Extensions");
    CompositionContainer container = new CompositionContainer(catalog.Resolver);
    container.AddComponent<User>(user);
    container.Bind();
    Console.WriteLine(user.Role);
    Console.ReadLine();
}

結語

MEF 的核心優勢在於 Duck Typing 與 Plug-In 支援,它不只是 DI 容器,更是完整的擴充管理框架。雖當時仍處 CTP 階段,但已展現極大潛力,未來更將支援 Silverlight 應用程式擴充。官方專案頁面:https://code.msdn.microsoft.com/mef。

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