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

.NET 外掛架構:從 C++ 動態載入 Managed 組件

     編輯:關於VC++

前言

許多 C++ 應用程式希望支援使用者以 C#、VB.NET 等 .NET 語言撰寫外掛。傳統 C++ 透過虛擬函數指標模擬 COM 介面,但 .NET 提供更簡潔的機制:組件動態載入 + 反射,無需註冊、GUID、參考計數等繁瑣 COM 細節。

基本概念:Assembly.Load 與反射

.NET 中對應 LoadLibrary 的是 System.Reflection.Assembly.Load / LoadFrom。載入組件後,可用反射取得型別、方法並動態呼叫:

Assembly asm = Assembly.Load("MyLib");
Type t = asm.GetType("MyLib.MyClass");
MethodInfo m = t.GetMethod("SayHello");
m.Invoke(null, new object[] { "Test" });

Load 依賴 Fusion 綁定規則(GAC、應用程式目錄等);LoadFrom 可指定路徑,適合外掛場景。

外掛架構設計:介面導向

  1. 定義介面組件(如 ITextPlugin.dll),僅含介面定義,無實作。
  2. 外掛開發者參考此組件,實作介面(如 public class MyPlugin : ITextPlugin)。
  3. 主程式啟動時掃描外掛目錄,載入每個組件,用反射尋找實作介面的型別並建立實例。

核心管理類別 CPluginMgr

public class CPluginMgr
{
    private List<object> m_objects = new List<object>();
    private string m_pluginDir;

    public CPluginMgr(string pluginDir = "Plugins") { m_pluginDir = pluginDir; }

    public int LoadAll(Type iface)
    {
        int count = 0;
        foreach (string dll in Directory.GetFiles(m_pluginDir, "*.dll"))
        {
            Assembly asm = Assembly.LoadFrom(dll);
            foreach (Type t in asm.GetTypes())
            {
                if (iface.IsAssignableFrom(t))
                {
                    object obj = Activator.CreateInstance(t);
                    m_objects.Add(obj);
                    count++;
                }
            }
        }
        return count;
    }

    public IEnumerable<T> GetPlugins<T>() where T : class
    {
        foreach (object o in m_objects)
            if (o is T plugin) yield return plugin;
    }
}

主程式啟動時:

m_plugins.LoadAll(typeof(ITextPlugin));

使用時:

foreach (ITextPlugin p in m_plugins.GetPlugins<ITextPlugin>())
    p.Transform(text);

效能優化建議

若外掛型別眾多,逐一檢查 IsAssignableFrom 會有效能負擔。建議採用 組件層級屬性 標記外掛型別,讓管理器快速定位,參考 Joel Pobar 在 MSDN 2005 年 7 月號文章。

AppDomain 隔離(進階)

若需運行時卸載/重載外掛,或限制外掛權限,必須將外掛載入獨立 AppDomain。跨域呼叫需型別繼承 MarshalByRefObject,透過 Remoting 封送。桌面應用若無熱插拔與沙箱需求,直接載入預設域即可。

完整範例:PGEdit 文字編輯器

  • 介面 ITextPlugin:MenuName、MenuPrompt、Transform(string)。
  • 三個外掛:PluginCaps(大寫)、PluginLower(小寫)、PluginScramble(打亂)。
  • 主視窗動態建立選單項目,命令 ID 從 IDC_PLUGIN_BASE 起算,用 ON_COMMAND_RANGE 分派。

Figure 5:帶有三個外掛的 PGEdit

結語

.NET 的語言中立特性使外掛架構極易實作:定義介面組件、動態載入組件、反射實例化。無需 COM 複雜度,即可讓使用者以任何 .NET 語言擴充應用程式功能。

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