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

MEF 實戰(三):只匯出類別成員(屬性/方法),不匯出整個類別

     編輯:關於C#

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(型別)必須與匯入端完全一致。
  • 屬性/方法匯出時,MEF 仍需實例化擁有者類別(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();
        }
    }
}

執行結果截圖

方法匯出執行結果

適用場景

  • 單一 Factory/Manager 類別集中管理多個擴充點(如 IValidator、IExporter)
  • 想把「建構邏輯」與「匯出契約」分離,避免建立大量單一職責的小類別
  • 動態決定要匯出哪些成員(搭配 ExportProvider 進階用法)

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

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