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

C# 反射完整實戰教學:動態載入 DLL、建立實例、呼叫方法 (含靜態/無參數)

     編輯:關於C語言

前言

反射讓 C# 程式在執行期發現型別資訊、動態建立物件、呼叫方法。本文完整示範:建立類別庫 DLL → 主程式反射載入 → 呼叫實例方法、靜態方法、無參數方法,並處理例外與資源釋放。

步驟 1:建立類別庫專案 (TestReflect.dll)

namespace Webtest
{
    public class ReflectTest
    {
        public ReflectTest() { }

        // 實例方法
        public string WriteString(string s) => "歡迎您," + s;

        // 靜態方法
        public static string WriteName(string s) => "歡迎您光臨," + s;

        // 無參數實例方法
        public string WriteNoPara() => "您使用的是無參數方法";
    }
}

編譯產出 TestReflect.dll 放置於 D:\。

步驟 2:主程式反射呼叫完整代碼

public void TestReflection()
{
    Assembly ass = null;
    Type type = null;
    object obj = null;

    try
    {
        // 1. 載入組件 (絕對路徑)
        ass = Assembly.LoadFile(@"D:\TestReflect.dll");

        // 2. 取得型別 (必須含命名空間)
        type = ass.GetType("Webtest.ReflectTest");

        // 3. 建立實例 (實例方法需物件)
        obj = ass.CreateInstance("Webtest.ReflectTest");

        // 4. 取得並呼叫實例方法
        var method = type.GetMethod("WriteString");
        string result = (string)method.Invoke(obj, new object[] { "jianglijun" });
        Console.WriteLine(result); // 歡迎您,jianglijun

        // 5. 取得並呼叫靜態方法 (第一參數傳 null)
        method = type.GetMethod("WriteName");
        result = (string)method.Invoke(null, new object[] { "jianglijun" });
        Console.WriteLine(result); // 歡迎您光臨,jianglijun

        // 6. 取得並呼叫無參數實例方法
        method = type.GetMethod("WriteNoPara");
        result = (string)method.Invoke(obj, null);
        Console.WriteLine(result); // 您使用的是無參數方法
    }
    catch (Exception ex)
    {
        Console.WriteLine("反射錯誤: " + ex.Message);
    }
    finally
    {
        // 釋放參考 (組件無法卸載,僅清除變數)
        ass = null; type = null; obj = null;
    }
}

關鍵 API 對照表

操作API關鍵參數
載入組件Assembly.LoadFile(path)絕對路徑,不鎖定檔案
載入組件Assembly.LoadFrom(path)相對路徑,會鎖定檔案
取得型別ass.GetType("Full.Name")命名空間+類別名,區分大小寫
建立實例ass.CreateInstance("Full.Name")呼叫無參建構函數
取得方法type.GetMethod("Name")可加 BindingFlags 過載搜尋私有/靜態
呼叫方法method.Invoke(obj, args[])靜態方法 obj 傳 null;陣列參數對應簽名

常見坑與解決方案

  • 型別名稱錯誤:必須包含完整命名空間,區分大小寫。
  • 方法多載:GetMethod 無參數版本回傳第一個匹配,建議使用 GetMethod("Name", new Type[] { typeof(string) }) 精確匹配簽名。
  • 私有成員:需 BindingFlags.NonPublic | BindingFlags.Instance。
  • 參數陣列:Invoke 第二參數為 object[],單一參數也要包在陣列 new object[] { val };無參傳 null 或 new object[0]。
  • 例外包裝:Invoke 拋出 TargetInvocationException,真實例外在 InnerException。
  • 組件卸載:.NET Framework 無法卸載組件,需使用 AssemblyLoadContext (.NET Core 3.0+) 實現插件熱重載。

效能優化建議

  1. 快取 Type/MethodInfo:反射查詢昂貴,靜態字典快取。
  2. 使用 Delegate.CreateDelegate:將 MethodInfo 轉為強型別委派,後續呼叫接近直接呼叫速度。
  3. 原始碼產生器 / Expression Tree:編譯期生成呼叫代碼,完全避免反射開銷。
  4. 總結

    反射是 C# 動態性的基石,支援插件架構、序列化、ORM、測試框架等核心基礎設施。掌握 Assembly.LoadFile、GetType、CreateInstance、GetMethod、Invoke 五大核心 API,並理解靜態/實例/無參數方法的呼叫差異,是進階 C# 開發者必備技能。生產代碼中務必加入快取與例外處理,必要時改用委派或原始碼產生提升效能。

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