MEF 核心概念:任何類別或介面實作皆可透過 [Export] 定義為可組合部件,導入端以 [Import] 組合,兩者透過契約通訊,本質即依賴注入與物件實例化。
使用字串契約名稱 "Message" 連結導出與導入:
public class StringProvider
{
[Export("Message")]
public string Output => "Hello World";
}
public class Client
{
[Import("Message")]
public string Input { get; set; }
public void Print() => Console.WriteLine(Input);
}
同一介面多個實作時,皆以介面型別為契約:
public interface ILogger
{
void WriteLog(string message);
}
[Export(typeof(ILogger))]
public class TXTLogger : ILogger { ... }
[Export(typeof(ILogger))]
public class DBLogger : ILogger { ... }
導入端使用 [ImportMany] 一次取得所有實作:
[ImportMany]
public IEnumerable<ILogger> Loggers { get; set; }
// 使用時
foreach (var logger in Loggers)
logger.WriteLog("Hello World");
ExportAttribute 與 ImportAttribute 均支援 (string contractName, Type contractType) 建構函式。為不同實作指定唯一契約名:
[Export("TXT", typeof(ILogger))]
public class TXTLogger : ILogger { ... }
[Export("DB", typeof(ILogger))]
public class DBLogger : ILogger { ... }
再透過門面服務聚合,依契約名精準導入:
[Export]
public class LogService
{
[Import("TXT")]
public ILogger TXTLogger { get; set; }
[Import("DB")]
public ILogger DBLogger { get; set; }
}
public partial class MainPage : UserControl
{
[Import]
public LogService Service { get; set; }
public MainPage()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
Service.DBLogger.WriteLog("Hello MEF");
Service.TXTLogger.WriteLog("Hello MEF");
}
}
此模式讓系統同時支援「取得所有實作」與「精準取得特定實作」兩種需求。