1. 反射簡介
2. 使用反射
3. 反射調用方法的執行機制
1. 反射簡介
程式集包含模組,而模組包含類型,類型又包含成員。反射則提供了封裝程式集、模組和類型的對象。您可以使用反射動態地建立類型的執行個體,將類型綁定到現有對象,或從現有對象中擷取類型。然後,可以調用類型的方法或訪問其欄位和屬性。(FROM MSDN)
2. 使用反射
2.1 反射物件模型(FROM 《Essential.Net》)
2.2 反射類型的階層(FROM 《Essential.Net》)
2.3 各個對象的建立方式和功能
| 對象 |
建立該對象 |
功能(FROM MSDN) |
| Assembly |
Assembly.Load Assembly.LoadFile Assembly.LoadFrom |
使用 定義和載入程式集,載入在資訊清單中列出的模組,以及從此程式集中尋找類型並建立該類型的執行個體。 |
|
Assembly.GetModule Assembly.GetModules |
使用 發現以下資訊:包含模組的程式集以及模組中的類等。您還可以擷取在模組上定義的所有全域方法或其他特定的非全域方法。 |
|
Type.GetConstructor Type.GetConstructors Type.GetConstructorImpl |
使用 發現以下資訊:建構函式的名稱、參數、存取修飾詞(如 public 或 private)和實現詳細資料(如 abstract 或 virtual)等。使用 的 或 方法來調用特定的建構函式。 |
|
Type.GetMethod Type.GetMethods Type.GetMethodImpl |
使用 發現以下資訊:方法的名稱、傳回型別、參數、存取修飾詞(如 public 或 private)和實現詳細資料(如 abstract 或 virtual)等。 |
|
Type.GetField Type.GetFields |
使用 發現以下資訊:欄位的名稱、存取修飾詞(如 public 或 private)和實現詳細資料(如 static)等;並擷取或設定欄位值。 |
|
Type.GetEvent Type.GetEvents |
使用 發現以下資訊:事件的名稱、事件處理常式資料類型、自訂屬性、宣告類型和反射類型等;並添加或移除事件處理常式。 |
|
Type.GetProperty Type.GetProperties Type.GetPropertyImpl |
使用 發現以下資訊:屬性的名稱、資料類型、宣告類型、反射類型和唯讀或可寫狀態等;並擷取或設定屬性值。 |
|
MethodBase.GetParameters |
使用 發現以下資訊:參數的名稱、資料類型、參數是輸入參數還是輸出參數,以及參數在方法簽名中的位置等。 |
| |
|
當您在一個應用程式定義域的僅反射內容中工作時,請使用 來瞭解有關自訂屬性的資訊。使用,您不必建立屬性的執行個體就可以檢查它們。 |
2.4 反射調用執行個體
namespace NameSpace
{
internal class Reflect
{
private int Add(int arg0, int arg1, int arg2)
{
return arg0 + arg1 + arg2;
}
}
class Program
{
internal static int CallAdd()
{
//指定TypeName建立對象執行個體
object target = Assembly.GetExecutingAssembly().CreateInstance("NameSpace.Reflect", true);
//取得方法
Type type = target.GetType();
MethodInfo methodInfo = type.GetMethod("Add", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
if (methodInfo == null)
return 0;
object[] args = new object[] { 10, 20, 30 };
object result = methodInfo.Invoke(target, args); //調用
return Convert.ToInt32(result);
}
}
}
3. 反射調用方法的執行機制
MethodInfo.Invoke使用提供的對象引用和參數來調用底層方法。其執行過程如下(FROM 《Essential.Net》):
(1). 構建一個堆疊框架;
(2). 將參數值拷貝到堆棧上;
(3). 調用目標方法(IA-32處理器的call指令);
(4). 方法執行完畢後,Invoke識別按引用傳遞的參數,並將他們拷貝回參數值數組中;
(5). 如果方法有傳回值,則將該值作為Invoke的傳回值。
展示了上面2.4中範例程式碼的執行過程:
補充:
1. 有關堆疊框架,可以參考:《Reversing:逆向工程揭密》 堆疊框架
2. 中,展示的是fastcall呼叫慣例,fastcall呼叫慣例通常使用ECX寄存器和EDX寄存器來分別存放第一個參數和第二個參數。有關呼叫慣例,可以參考:《Reversing:逆向工程揭密》 呼叫慣例