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

C# 反射動態載入 DLL 並呼叫方法完整教學

     編輯:關於C#

應用場景

外掛架構、模組化系統、延遲載入非核心組件、測試框架自動發現測試類別等,均需在執行期動態載入組件並實例化型別、呼叫方法。

步驟 1:建立目標 DLL 專案 (Class Library)

// 專案名: ReflectTarget, 輸出 ReflectTarget.dll
namespace ReflectTarget
{
    public class Calculator
    {
        public Calculator() { Console.WriteLine("Calculator 建構子執行"); }

        public int Add(int a, int b) => a + b;

        public string GetMessage(string name) => $"Hello, {name} from DLL!";

        public static string StaticMethod() => "Static method called.";
    }
}

編譯後取得 ReflectTarget.dll。

步驟 2:主程式動態載入並呼叫

using System;
using System.Reflection;
using System.IO;

class Program
{
    static void Main()
    {
        string dllPath = @"C:\Path\To\ReflectTarget.dll"; // 實際路徑

        if (!File.Exists(dllPath))
        {
            Console.WriteLine("DLL 不存在");
            return;
        }

        // 1. 載入組件 (三種方式擇一)
        // Assembly asm = Assembly.LoadFile(dllPath);           // 完整路徑載入,不進入載入上下文
        // Assembly asm = Assembly.LoadFrom(dllPath);           // 載入上下文,解析相依性較好
        Assembly asm = Assembly.Load(File.ReadAllBytes(dllPath)); // 位元組陣列載入,最隔離

        // 2. 取得型別 (需含命名空間)
        Type calcType = asm.GetType("ReflectTarget.Calculator");
        if (calcType == null)
        {
            Console.WriteLine("找不到型別");
            return;
        }

        // 3. 建立實例 (無參數建構子)
        object instance = Activator.CreateInstance(calcType);
        // 若有參數建構子:Activator.CreateInstance(calcType, arg1, arg2);

        // 4. 呼叫實例方法
        MethodInfo addMethod = calcType.GetMethod("Add");
        int result = (int)addMethod.Invoke(instance, new object[] { 10, 20 });
        Console.WriteLine($"Add(10,20) = {result}");

        MethodInfo msgMethod = calcType.GetMethod("GetMessage");
        string msg = (string)msgMethod.Invoke(instance, new object[] { "Alice" });
        Console.WriteLine(msg);

        // 5. 呼叫靜態方法 (instance 可傳 null)
        MethodInfo staticMethod = calcType.GetMethod("StaticMethod");
        string staticResult = (string)staticMethod.Invoke(null, null);
        Console.WriteLine(staticResult);
    }
}

關鍵 API 對照

需求API備註
載入檔案路徑Assembly.LoadFile(path)不解析相依組件,隔離性高
載入並解析相依Assembly.LoadFrom(path)進入 LoadFrom 上下文
載入位元組陣列Assembly.Load(byte[])記憶體中載入,無檔案鎖定
取得型別asm.GetType("Full.Name")區分大小寫,需含命名空間
建立實例Activator.CreateInstance(type)支援建構子參數
取得方法type.GetMethod("Name")可加 BindingFlags 找私有/靜態/多載
呼叫方法method.Invoke(obj, args[])靜態方法 obj 傳 null

進階技巧

  • 介面契約: 定義共用介面 DLL,主程式與外掛皆參考,動態載入後 instance as IPlugin 強型別呼叫,避免反射效能損耗。
  • 泛型方法呼叫: method.MakeGenericMethod(typeof(T)).Invoke(...)。
  • 非公用成員: GetMethod("Name", BindingFlags.NonPublic | BindingFlags.Instance)。
  • 卸載組件: .NET Framework 無法單獨卸載組件,需建立獨立 AppDomain 載入,卸載時 AppDomain.Unload(domain)。.NET Core 3.0+ 支援 AssemblyLoadContext 卸載。

常見錯誤排查

例外原因解決
FileNotFoundException相依 DLL 找不到將相依 DLL 放同目錄、或處理 AssemblyResolve 事件
MissingMethodException方法簽章不符、建構子參數錯誤檢查 GetMethod 參數、BindingFlags、建構子參數順序
TargetInvocationException方法內部拋出例外捕獲 ex.InnerException 才是真正原因
BadImageFormatException位元數不符 (x86/x64)專案目標平台與 DLL 一致,或用 CorFlags 強制

參考資源

原文連結:https://www.bianceng.cn/Programming/csharp/201410/45595.htm

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