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 | 使用 | |
Type.GetMethod Type.GetMethods Type.GetMethodImpl | 使用 | |
Type.GetField Type.GetFields | 使用 | |
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:逆向工程揭密》 调用约定