MEF 的 [Export] 不只能貼在類別上,也能貼在 屬性、欄位、方法 上。這讓「單一類別管理多個擴充點」成為可能:一個 Works 類別內建 FirstWork/SecondWork 兩個屬性,分別匯出為 IWork;另有一個方法 ViewWork 匯出為 Func<string>。匯入端對應使用 [Import] 或 [ImportMany] 接收。
public interface IWork {
void DoSome();
string WName { get; }
}
public class FirstWork : IWork { /* ... */ }
public class SecondWork : IWork { /* ... */ }
public class Works {
private readonly FirstWork _fw = new();
private readonly SecondWork _sw = new();
[Export("work1", typeof(IWork))]
public IWork WorkFirst => _fw;
[Export("work2", typeof(IWork))]
public IWork WorkSecond => _sw;
[Export("viewWork", typeof(Func<string>))]
public string ViewWork() => "本生產線國際一流,由 3172 個工作單元組成...";
}
public class Program {
[Import("work1", typeof(IWork))]
public IWork TheFirstWork { get; set; }
[Import("work2", typeof(IWork))]
public IWork TheSecondWork { get; set; }
[Import("viewWork", typeof(Func<string>))]
public Func<string> TheViewWork { get; set; }
}
關鍵點:
ContractName(字串)與 ContractType(型別)必須與匯入端完全一致。Works),故匯入端不可用 Lazy<T>(會無法建立實例),直接用強型別屬性接收。Func<TResult> / Action<T> 等委派型別作為 ContractType,語意最清晰。using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Reflection;
namespace MefApp {
public interface IWork {
void DoSome();
string WName { get; }
}
public class FirstWork : IWork {
public void DoSome() => Console.WriteLine("工序一執行。");
public string WName => "工序一";
}
public class SecondWork : IWork {
public void DoSome() => Console.WriteLine("工序二執行。");
public string WName => "工序二";
}
public class Works {
private readonly FirstWork _fw = new();
private readonly SecondWork _sw = new();
[Export("work1", typeof(IWork))] public IWork WorkFirst => _fw;
[Export("work2", typeof(IWork))] public IWork WorkSecond => _sw;
[Export("viewWork", typeof(Func<string>))]
public string ViewWork() => "本生產線國際一流,由3172個工作單元組成,73265道工序。";
}
class Program {
[Import("work1", typeof(IWork))] public IWork TheFirstWork;
[Import("work2", typeof(IWork))] public IWork TheSecondWork;
[Import("viewWork", typeof(Func<string>))] public Func<string> TheViewWork;
static void Main() {
var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var container = new CompositionContainer(catalog);
var p = new Program();
container.SatisfyImportsOnce(p);
p.TheFirstWork?.DoSome();
p.TheSecondWork?.DoSome();
Console.WriteLine(p.TheViewWork?.Invoke());
container.Dispose();
Console.Read();
}
}
}


IValidator、IExporter)ExportProvider 進階用法)成員級匯出讓 MEF 粒度更細、組合更靈活。下次寫 Manager 類別時,考慮把內部的多個策略屬性直接 [Export],省去一堆 class XxxStrategy : IStrategy 的樣板碼。