以下是CodeGenerator类用的一些辅助类:
Cmp比较类型
1 /// <summary> 2 /// Cmp 3 /// </summary> 4 public enum Cmp 5 { 6 /// <summary> 7 /// LessThan 8 /// </summary> 9 LessThan, 10 /// <summary> 11 /// EqualTo 12 /// </summary> 13 EqualTo, 14 /// <summary> 15 /// LessThanOrEqualTo 16 /// </summary> 17 LessThanOrEqualTo, 18 /// <summary> 19 /// GreaterThan 20 /// </summary> 21 GreaterThan, 22 /// <summary> 23 /// NotEqualTo 24 /// </summary> 25 NotEqualTo, 26 /// <summary> 27 /// GreaterThanOrEqualTo 28 /// </summary> 29 GreaterThanOrEqualTo 30 }
ArgBuilder方法参数定义
1 /// <summary> 2 /// ArgBuilder 3 /// </summary> 4 public class ArgBuilder 5 { 6 /// <summary> 7 /// ArgType 8 /// </summary> 9 public Type ArgType; 10 /// <summary> 11 /// Index 12 /// </summary> 13 public int Index; 14 15 /// <summary> 16 /// ArgBuilder 17 /// </summary> 18 /// <param name="index"></param> 19 /// <param name="argType"></param> 20 public ArgBuilder(int index, Type argType) 21 { 22 this.Index = index; 23 this.ArgType = argType; 24 } 25 }
IfState[If语句之状态]
1 /// <summary> 2 /// IfState 3 /// </summary> 4 public class IfState 5 { 6 // Fields 7 private Label elseBegin; 8 private Label endIf; 9 10 /// <summary> 11 /// ElseBegin 12 /// </summary> 13 public Label ElseBegin 14 { 15 get 16 { 17 return this.elseBegin; 18 } 19 set 20 { 21 this.elseBegin = value; 22 } 23 } 24 25 /// <summary> 26 /// EndIf 27 /// </summary> 28 public Label EndIf 29 { 30 get 31 { 32 return this.endIf; 33 } 34 set 35 { 36 this.endIf = value; 37 } 38 } 39 }
SwitchState[Switch语句之状态]
1 /// <summary> 2 /// SwitchState 3 /// </summary> 4 public class SwitchState 5 { 6 private bool defaultDefined; 7 private Label defaultLabel; 8 private Label endOfSwitchLabel; 9 10 /// <summary> 11 /// SwitchState 12 /// </summary> 13 /// <param name="defaultLabel"></param> 14 /// <param name="endOfSwitchLabel"></param> 15 public SwitchState(Label defaultLabel, Label endOfSwitchLabel) 16 { 17 this.defaultLabel = defaultLabel; 18 this.endOfSwitchLabel = endOfSwitchLabel; 19 this.defaultDefined = false; 20 } 21 22 /// <summary> 23 /// DefaultDefined 24 /// </summary> 25 public bool DefaultDefined 26 { 27 get 28 { 29 return this.defaultDefined; 30 } 31 set 32 { 33 this.defaultDefined = value; 34 } 35 } 36 37 /// <summary> 38 /// DefaultLabel 39 /// </summary> 40 public Label DefaultLabel 41 { 42 get 43 { 44 return this.defaultLabel; 45 } 46 } 47 48 /// <summary> 49 /// EndOfSwitchLabel 50 /// </summary> 51 public Label EndOfSwitchLabel 52 { 53 get 54 { 55 return this.endOfSwitchLabel; 56 } 57 } 58 }
ForState[For语句之状态]
1 /// <summary> 2 /// ForState 3 /// </summary> 4 public class ForState 5 { 6 // Fields 7 private Label beginLabel; 8 private object end; 9 private Label endLabel; 10 private LocalBuilder indexVar; 11 private bool requiresEndLabel; 12 private Label testLabel; 13 14 /// <summary> 15 /// ForState 16 /// </summary> 17 /// <param name="indexVar"></param> 18 /// <param name="beginLabel"></param> 19 /// <param name="testLabel"></param> 20 /// <param name="end"></param> 21 public ForState(LocalBuilder indexVar, Label beginLabel, Label testLabel, object end) 22 { 23 this.indexVar = indexVar; 24 this.beginLabel = beginLabel; 25 this.testLabel = testLabel; 26 this.end = end; 27 } 28 29 /// <summary> 30 /// BeginLabel 31 /// </summary> 32 public Label BeginLabel 33 { 34 get 35 { 36 return this.beginLabel; 37 } 38 } 39 40 /// <summary> 41 /// End 42 /// </summary> 43 public object End 44 { 45 get 46 { 47 return this.end; 48 } 49 } 50 51 /// <summary> 52 /// EndLabel 53 /// </summary> 54 public Label EndLabel 55 { 56 get 57 { 58 return this.endLabel; 59 } 60 set 61 { 62 this.endLabel = value; 63 } 64 } 65 66 /// <summary> 67 /// Index 68 /// </summary> 69 public LocalBuilder Index 70 { 71 get 72 { 73 return this.indexVar; 74 } 75 } 76 77 /// <summary> 78 /// RequiresEndLabel 79 /// </summary> 80 public bool RequiresEndLabel 81 { 82 get 83 { 84 return this.requiresEndLabel; 85 } 86 set 87 { 88 this.requiresEndLabel = value; 89 } 90 } 91 92 /// <summary> 93 /// TestLabel 94 /// </summary> 95 public Label TestLabel 96 { 97 get 98 { 99 return this.testLabel; 100 } 101 } 102 }
介绍一下 ILGenerator :
其主要功能是:将指定的指令放到指令流上,构建方法体所用。
用于为动态程序集中的方法和构造函数(由 MethodBuilder 和 ConstructorBuilder 类表示)以及为独立动态方法(由 DynamicMethod 类表示)生成方法体。
若要获取 ILGenerator,请使用 ConstructorBuilder.GetILGenerator、DynamicMethod.GetILGenerator 和 MethodBuilder.GetILGenerator 方法。
字段主要分:方法体的环境变量,常用工具方法的MethodInfo
字段定义
1 private ILGenerator ilGen; 2 private Module serializationModule = typeof(CodeGenerator).Module; 3 4 5 //构建方法体主要的环境变量 6 private Type delegateType; 7 private DynamicMethod dynamicMethod; //当前类是通过委托,构建动态方法时用到 8 private MethodBase methodOrConstructorBuilder; //当前类使用第3个构造方法时用到 9 private Stack blockStack; 10 private ArrayList argList; 11 private Hashtable localNames; 12 private LocalBuilder stringFormatArray; 13 private Label methodEndLabel; 14 15 //常用工具方法 16 private static MethodInfo getTypeFromHandle; 17 private static MethodInfo objectEquals; 18 private static MethodInfo objectToString; 19 private static MethodInfo stringConcat2; 20 private static MethodInfo stringConcat3; 21 private static MethodInfo stringFormat;
常量加载
1 /// <summary> 2 /// Ldc 通过Ldc指令加载布尔值到计算堆栈 true 为 1,false 为0 3 /// </summary> 4 /// <param name="boolVar"></param> 5 public void Ldc(bool boolVar) 6 { 7 if (boolVar) 8 { 9 this.ilGen.Emit(OpCodes.Ldc_I4_1); 10 } 11 else 12 { 13 this.ilGen.Emit(OpCodes.Ldc_I4_0); 14 } 15 } 16 17 18 19 /// <summary> 20 /// Ldc 加载整型数值到计算堆栈 21 /// <list type=""> 22 /// ldc.i4.m1 (ldc.i4.M1) -1 23 /// ldc.i4.0 0 24 /// ... 25 /// ldc.i4.8 8 26 /// Ldc_I4 普通整数 27 /// </list> 28 /// </summary> 29 /// <param name="intVar"></param> 30 public void Ldc(int intVar) 31 { 32 switch (intVar) 33 { 34 case -1: 35 this.ilGen.Emit(OpCodes.Ldc_I4_M1); 36 return; 37 38 case 0: 39 this.ilGen.Emit(OpCodes.Ldc_I4_0); 40 return; 41 42 case 1: 43 this.ilGen.Emit(OpCodes.Ldc_I4_1); 44 return; 45 46 case 2: 47 this.ilGen.Emit(OpCodes.Ldc_I4_2); 48 return; 49 50 case 3: 51 this.ilGen.Emit(OpCodes.Ldc_I4_3); 52 return; 53 54 case 4: 55 this.ilGen.Emit(OpCodes.Ldc_I4_4); 56 return; 57 58 case 5: 59 this.ilGen.Emit(OpCodes.Ldc_I4_5); 60 return; 61 62 case 6: 63 this.ilGen.Emit(OpCodes.Ldc_I4_6); 64 return; 65 66 case 7: 67 this.ilGen.Emit(OpCodes.Ldc_I4_7); 68 return; 69 70 case 8: 71 this.ilGen.Emit(OpCodes.Ldc_I4_8); 72 return; 73 } 74 this.ilGen.Emit(OpCodes.Ldc_I4, intVar); 75 } 76 77 /// <summary> 78 /// Ldc 加载长整数到计算堆栈 对应指令 ldc.i8 79 /// </summary> 80 /// <param name="l">The l.</param> 81 public void Ldc(long l) 82 { 83 this.ilGen.Emit(OpCodes.Ldc_I8, l); 84 } 85 86 /// <summary> 87 /// Ldc 加载单精度浮点数到计算堆栈 88 /// </summary> 89 /// <param name="f"></param> 90 public void Ldc(float f) 91 { 92 this.ilGen.Emit(OpCodes.Ldc_R4, f); 93 } 94 95 /// <summary> 96 /// Ldc 加载双精度浮点数到计算堆栈 对应指令:Ldc_R8 97 /// </summary> 98 /// <param name="d"></param> 99 public void Ldc(double d) 100 { 101 this.ilGen.Emit(OpCodes.Ldc_R8, d); 102 } 103 104 /// <summary> 105 /// Ldc 传入一个未知类型对象,根据其类型,自动调用适合的指令来将它加载到计算堆栈 106 /// </summary> 107 /// <param name="o"></param> 108 public void Ldc(object o) 109 { 110 Type enumType = o.GetType(); 111 if (o is Type)//类型变量 112 { 113 //相当于 typeof(o); 114 this.Ldtoken((Type)o); 115 this.Call(GetTypeFromHandle); 116 } 117 else if (enumType.IsEnum) 118 { 119 //Enum.GetUnderlyingType(enumType):返回指定的枚举的基础类型,即枚举定义类型 120 //枚举类型转为 数值类型 121 this.Ldc(((IConvertible)o).ToType(Enum.GetUnderlyingType(enumType), null)); 122 } 123 else 124 { 125 switch (Type.GetTypeCode(enumType)) 126 { 127 case TypeCode.Boolean: 128 this.Ldc((bool)o); 129 return; 130 131 case TypeCode.Char: 132 //throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException(SR.GetString("CharIsInvalidPrimitive"))); 133 134 case TypeCode.SByte: 135 case TypeCode.Byte: 136 case TypeCode.Int16: 137 case TypeCode.UInt16: 138 this.Ldc(((IConvertible)o).ToInt32(CultureInfo.InvariantCulture)); 139 return; 140 141 case TypeCode.Int32: 142 this.Ldc((int)o); 143 return; 144 145 case TypeCode.UInt32: 146 this.Ldc((int)((uint)o)); 147 return; 148 149 case TypeCode.Int64: 150 this.Ldc((long)o); 151 return; 152 153 case TypeCode.UInt64: 154 this.Ldc((long)((ulong)o)); 155 return; 156 157 case TypeCode.Single: 158 this.Ldc((float)o); 159 return; 160 161 case TypeCode.Double: 162 this.Ldc((double)o); 163 return; 164 165 case TypeCode.String: 166 this.Ldstr((string)o); 167 return; 168 } 169 throw new Exception("UnknownConstantType"); 170 } 171 }
局部变量定义
1 /// <summary> 2 /// DeclareLocal 3 /// </summary> 4 /// <param name="type"></param> 5 /// <returns></returns> 6 public LocalBuilder DeclareLocal(Type type) 7 { 8 Check.Require(type, "type"); 9 10 return this.DeclareLocal(type, null, false); 11 } 12 13 /// <summary> 14 /// DeclareLocal 15 /// </summary> 16 /// <param name="type"></param> 17 /// <param name="name"></param> 18 /// <returns></returns> 19 public LocalBuilder DeclareLocal(Type type, string name) 20 { 21 Check.Require(type, "type"); 22 23 return this.DeclareLocal(type, name, false); 24 } 25 26 /// <summary> 27 /// DeclareLocal 28 /// </summary> 29 /// <param name="type"></param> 30 /// <param name="name"></param> 31 /// <param name="isPinned"></param> 32 /// <returns></returns> 33 public LocalBuilder DeclareLocal(Type type, string name, bool isPinned) 34 { 35 Check.Require(type, "type"); 36 37 LocalBuilder builder = this.ilGen.DeclareLocal(type, isPinned); 38 return builder; 39 } 40 41 /// <summary> 42 /// DeclareLocal 43 /// </summary> 44 /// <param name="type"></param> 45 /// <param name="name"></param> 46 /// <param name="initialValue"></param> 47 /// <returns></returns> 48 public LocalBuilder DeclareLocal(Type type, string name, object initialValue) 49 { 50 Check.Require(type, "type"); 51 52 LocalBuilder var = this.DeclareLocal(type, name); 53 this.Load(initialValue); 54 this.Store(var); 55 return var; 56 }
变量:局部变量,参数变量,常量,静态变量。 分类:值类型,引用类型(属性值,数组)
变量存储
1 /// <summary> 2 /// Set: 3 /// </summary> 4 /// <param name="local"></param> 5 /// <param name="value"></param> 6 public void Set(LocalBuilder local, object value) 7 { 8 Check.Require(local, "local"); 9 10 this.Load(value); 11 this.Store(local); 12 } 13 14 /// <summary> 15 /// Starg 16 /// </summary> 17 /// <param name="slot"></param> 18 public void Starg(int slot) 19 { 20 if (slot <= 0xff) 21 { 22 this.ilGen.Emit(OpCodes.Starg_S, slot); 23 } 24 else 25 { 26 this.ilGen.Emit(OpCodes.Starg, slot); 27 } 28 } 29 30 /// <summary> 31 /// Starg 32 /// </summary> 33 /// <param name="arg"></param> 34 public void Starg(ArgBuilder arg) 35 { 36 Check.Require(arg, "arg"); 37 38 this.Starg(arg.Index); 39 } 40 41 /// <summary> 9 42 /// Stelem 43 /// </summary> 44 /// <param name="arrayElementType"></param> 45 public void Stelem(Type arrayElementType) 46 { 47 Check.Require(arrayElementType, "arrayElementType"); 48 49 if (arrayElementType.IsEnum) 50 { 51 this.Stelem(Enum.GetUnderlyingType(arrayElementType)); 52 } 53 else 54 { 55 OpCode opcode = this.GetStelemOpCode(Type.GetTypeCode(arrayElementType)); 56 if (opcode.Equals(OpCodes.Nop)) 57 { 58 throw new Exception("ArrayTypeIsNotSupported"); 59 } 60 this.ilGen.Emit(opcode); 61 } 62 } 63 64 /// <summary> 65 /// Stloc: 从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中。 66 /// </summary> 67 /// <param name="slot"></param> 68 public void Stloc(int slot) 69 { 70 switch (slot) 71 { 72 case 0: 73 this.ilGen.Emit(OpCodes.Stloc_0); 74 return; 75 76 case 1: 77 this.ilGen.Emit(OpCodes.Stloc_1); 78 return; 79 80 case 2: 81 this.ilGen.Emit(OpCodes.Stloc_2); 82 return; 83 84 case 3: 85 this.ilGen.Emit(OpCodes.Stloc_3); 86 return; 87 } 88 if (slot <= 0xff) 89 { 90 this.ilGen.Emit(OpCodes.Stloc_S, slot); 91 } 92 else 93 { 94 this.ilGen.Emit(OpCodes.Stloc, slot); 95 } 96 } 97 98 /// <summary> 99 /// Stloc:从计算堆栈的顶部弹出当前值并将其存储到指定索引处的局部变量列表中。 100 /// 提示:LocalBuilder对象包含局部变量的索引跟类型 101 /// </summary> 102 /// <param name="local"></param> 103 public void Stloc(LocalBuilder local) 104 { 105 Check.Require(local, "local"); 106 107 this.ilGen.Emit(OpCodes.Stloc, local); 108 } 109 110 /// <summary> 111 /// Stobj:将指定类型的值从计算堆栈复制到所提供的内存地址中。 112 /// Pre1: 将地址推送到堆栈上。 113 /// Pre2: 将 class 类型的值类型对象推送到堆栈上。 114 /// TODO: 从堆栈中弹出对象和地址;将值类型对象存储在该地址。 115 /// 参考: http://msdn.microsoft.com/zh-cn/library/system.reflection.emit.opcodes.stobj.aspx 116 /// </summary> 117 /// <param name="type"></param> 118 public void Stobj(Type type) 119 { 120 Check.Require(type, "type"); 121 122 this.ilGen.Emit(OpCodes.Stobj, type); 123 } 124 125 /// <summary> 126 /// Store:保存参数变量或局部变量 127 /// </summary> 128 /// <param name="var"></param> 129 public void Store(object var) 130 { 131 if (var is ArgBuilder) 132 { 133 this.Starg((ArgBuilder)var); 134 } 135 else 136 { 137 if (!(var is LocalBuilder)) 138 { 139 throw new Exception("CanOnlyStoreIntoArgOrLocGot0"); 140 } 141 this.Stloc((LocalBuilder)var); 142 } 143 } 144 145 /// <summary> 146 /// StoreArrayElement 147 /// </summary> 148 /// <param name="obj">数组对象</param> 149 /// <param name="arrayIndex">数组索引</param> 150 /// <param name="value">保存的值</param> 151 152 public void StoreArrayElement(object obj, object arrayIndex, object value) 153 { 154 Type variableType = this.GetVariableType(obj); 155 Type objType = (variableType == typeof(Array)) ? typeof(object) : variableType.GetElementType(); 156 this.Load(obj); 157 this.Load(arrayIndex); 158 159 if (IsStruct(objType)) 160 { 161 //Pre1:将对象引用 array 推送到堆栈上。 162 //Pre2:将索引值 index 推送到堆栈上。 163 //Do1:从堆栈中弹出 index 和 array;查找存储在array中的位置index 处的地址。 164 //Do2:将地址推送到堆栈上。 165 this.Ldelema(objType); 166 } 167 168 this.Load(value); 169 this.ConvertValue(this.GetVariableType(value), objType); 170 171 172 if (IsStruct(objType)) 173 { //Pre1: 将地址推送到堆栈上。 174 //Pre2: 将 class 类型的值类型对象推送到堆栈上。 175 //ToDo: 从堆栈中弹出对象和地址;将值类型对象存储在该地址。 176 this.Stobj(objType); 177 } 178 else 179 { 180 //Pre1: 将对数组 array 的对象引用推送到堆栈上。 181 //Pre2: 将array 中元素的有效索引推送到堆栈上。 182 //Pre3:将值推送到堆栈上。 183 //ToDo: 从堆栈中弹出值、索引和数组引用;将值放入给定索引处的数组元素中。 184 this.Stelem(objType); 185 } 186 } 187 188 /// <summary> 189 /// StoreMember 用新值替换在对象引用或指针的字段中存储的值 190 /// Pre:value压入栈中 191 /// </summary> 192 /// <param name="memberInfo"></param> 193 public void StoreMember(MemberInfo memberInfo) 194 { 195 Check.Require(memberInfo, "memberInfo"); 196 197 if (memberInfo.MemberType == MemberTypes.Field) 198 { 199 FieldInfo field = (FieldInfo)memberInfo; 200 if (field.IsStatic) 201 { 202 this.ilGen.Emit(OpCodes.Stsfld, field); 203 } 204 else 205 { 206 this.ilGen.Emit(OpCodes.Stfld, field); 207 } 208 } 209 else if (memberInfo.MemberType == MemberTypes.Property) 210 { 211 PropertyInfo info2 = memberInfo as PropertyInfo; 212 if (info2 != null) 213 { 214 MethodInfo methodInfo = info2.GetSetMethod(true); 215 if (methodInfo == null) 216 { 217 throw new Exception("NoSetMethodForProperty"); 218 } 219 this.Call(methodInfo); 220 } 221 } 222 else 223 { 224 if (memberInfo.MemberType != MemberTypes.Method) 225 { 226 throw new Exception("CannotLoadMemberType"); 227 } 228 this.Call((MethodInfo)memberInfo); 229 } 230 }
变量加载
1 /// <summary> 2 /// LdargAddress 加载参数地址。IL没有这个指令,它根据参数的类型分别调用不同的IL指令: 3 /// 当参数为值类型时,通过调用Ldarga指令,加载参数地址 4 /// 当参不为值类型时,直接调用Ldarg加载参数 5 /// 推测:maybe, 引用类型的变量本身代表的就是其地址,而值类型变量代表的是值本身,故值类型需要取址. 6 /// </summary> 7 /// <param name="argBuilder"></param> 8 public void LdargAddress(ArgBuilder argBuilder) 9 { 10 Check.Require(argBuilder, "argBuilder"); 11 12 if (argBuilder.ArgType.IsValueType) 13 { 14 this.Ldarga(argBuilder); 15 } 16 else 17 { 18 this.Ldarg(argBuilder); 19 } 20 } 21 22 23 /// <summary> 24 /// Ldelem 根据传入的数组类型,自动选择不同的指令,将位于数组指定索引处的元素加到计算堆栈 25 /// 这些指令包括: 26 /// ldelem.i1 加载int8 27 /// ldelem.u1 unsigned int8. 28 /// ldelem.i2 int16 29 /// ldelem.u2 unsigned int16 30 /// ldelem.i4 int32 31 /// ldelem.i8 int64 32 /// ldelem.i native int 33 /// ldelem.r4 float32 34 /// ldelem.r8 float64 35 /// ldelem.ref reference type 36 /// </summary> 37 /// <param name="arrayElementType"></param> 38 public void Ldelem(Type arrayElementType) 39 { 40 Check.Require(arrayElementType, "arrayElementType"); 41 42 if (arrayElementType.IsEnum) 43 { 44 this.Ldelem(Enum.GetUnderlyingType(arrayElementType)); 45 } 46 else 47 { 48 OpCode opcode = this.GetLdelemOpCode(Type.GetTypeCode(arrayElementType)); 49 if (opcode.Equals(OpCodes.Nop)) 50 { 51 throw new Exception("ArrayTypeIsNotSupported"); 52 } 53 this.ilGen.Emit(opcode); 54 } 55 } 56 57 /// <summary> 58 /// Ldelema 将位于指定数组索引的数组元素的地址作为 & 类型(托管指针)加载到计算堆栈的顶部。 59 /// </summary> 60 /// <param name="arrayElementType"></param> 61 public void Ldelema(Type arrayElementType) 62 { 63 Check.Require(arrayElementType, "arrayElementType"); 64 65 OpCode opcode = OpCodes.Ldelema; 66 this.ilGen.Emit(opcode, arrayElementType); 67 } 68 69 /// <summary> 70 /// Ldlen 将从零开始的、一维数组的元素的数目推送到计算堆栈上。 71 /// </summary> 72 public void Ldlen() 73 { 74 // Pre: 将对数组的对象引用推送到堆栈上。 75 // ToDo1:从堆栈中弹出数组引用,并计算长度。 76 // ToDo2:将长度推送到堆栈上。 77 this.ilGen.Emit(OpCodes.Ldlen); 78 // Pre: value 被推送到堆栈上。 79 // ToDo1: 从堆栈中弹出 value,然后尝试执行转换操作。 80 // ToDo2: 如果转换成功,则将结果值推送到堆栈上。 81 this.ilGen.Emit(OpCodes.Conv_I4); 82 } 83 84 /// <summary> 85 /// Ldloc 将指定索引处的局部变量加载到计算堆栈上。 86 /// </summary> 87 /// <param name="slot"></param> 88 public void Ldloc(int slot) 89 { 90 switch (slot) 91 { 92 case 0: 93 this.ilGen.Emit(OpCodes.Ldloc_0); 94 return; 95 96 case 1: 97 this.ilGen.Emit(OpCodes.Ldloc_1); 98 return; 99 100 case 2: 101 this.ilGen.Emit(OpCodes.Ldloc_2); 102 return; 103 104 case 3: 105 this.ilGen.Emit(OpCodes.Ldloc_3); 106 return; 107 } 108 if (slot <= 0xff) 109 { 110 this.ilGen.Emit(OpCodes.Ldloc_S, slot); 111 } 112 else 113 { 114 this.ilGen.Emit(OpCodes.Ldloc, slot); 115 } 116 } 117 118 /// <summary> 119 /// Ldloc 将指定索引处的局部变量加载到计算堆栈上 120 /// </summary> 121 /// <param name="localBuilder"></param> 122 public void Ldloc(LocalBuilder localBuilder) 123 { 124 this.ilGen.Emit(OpCodes.Ldloc, localBuilder); 125 } 126 127 /// <summary> 128 /// Ldloca 将位于特定索引处的局部变量的地址加载到计算堆栈上。 129 /// 提示:ldloca.s 指令为使用局部变量 0 到 255 提供有效的编码。 130 /// </summary> 131 /// <param name="slot"></param> 132 public void Ldloca(int slot) 133 { 134 if (slot <= 0xff) 135 { 136 this.ilGen.Emit(OpCodes.Ldloca_S, slot); 137 } 138 else 139 { 140 this.ilGen.Emit(OpCodes.Ldloca, slot); 141 } 142 } 143 144 /// <summary> 145 /// Ldloca 146 /// </summary> 147 /// <param name="localBuilder"></param> 148 public void Ldloca(LocalBuilder localBuilder) 149 { 150 Check.Require(localBuilder, "localBuilder"); 151 152 this.ilGen.Emit(OpCodes.Ldloca, localBuilder); 153 } 154 155 /// <summary> 156 /// LdlocAddress 不是IL指令。 157 /// 分别调用Ldloca和Ldloc将值/引用类型变量地址加载到计算堆栈 158 /// 当是为值类型时调用 Ldloca 159 /// 否则调用 Ldloc 160 /// </summary> 161 /// <param name="localBuilder"></param> 162 public void LdlocAddress(LocalBuilder localBuilder) 163 { 164 Check.Require(localBuilder, "localBuilder"); 165 166 if (localBuilder.LocalType.IsValueType) 167 { 168 this.Ldloca(localBuilder); 169 } 170 else 171 { 172 this.Ldloc(localBuilder); 173 } 174 } 175 176 /// <summary> 177 /// Ldobj 将地址指向的值类型(类型为type)对象复制到计算堆栈的顶部 178 /// </summary> 179 /// <param name="type"></param> 180 public void Ldobj(Type type) 181 { 182 Check.Require(type, "type"); 183 184 OpCode opcode = this.GetLdindOpCode(Type.GetTypeCode(type)); 185 if (!opcode.Equals(OpCodes.Nop)) 186 { 187 this.ilGen.Emit(opcode); 188 } 189 else 190 { 191 this.ilGen.Emit(OpCodes.Ldobj, type); 192 } 193 } 194 195 /// <summary> 196 /// Ldstr 197 /// 将一个字符串加载到 Stack 198 /// </summary> 199 /// <param name="strVar"></param> 200 public void Ldstr(string strVar) 201 { 202 this.ilGen.Emit(OpCodes.Ldstr, strVar); 203 } 204 205 /// <summary> 206 /// Ldtoken 将元数据标记(数据类型)转换为其运行时表示形式,并将其推送到计算堆栈上。 207 /// ldtoken 指令为指定的元数据标记推送 RuntimeHandle。 208 /// 其中: RuntimeHandle 可以是 fieldref/fielddef、methodref/methoddef 或 typeref/typedef。 209 /// 说白了:就是向栈内添加 某类型的 运行时类型 210 /// </summary> 211 /// <param name="t"></param> 212 public void Ldtoken(Type t) 213 { 214 Check.Require(t, "t"); 215 this.ilGen.Emit(OpCodes.Ldtoken, t); 216 } 217 218 /// <summary> 219 /// Load 220 /// </summary> 221 /// <param name="obj"></param> 222 public void Load(object obj) 223 { 224 if (obj == null) 225 { 226 this.ilGen.Emit(OpCodes.Ldnull); //将空对象引用推送到堆栈上 227 } 228 else if (obj is ArgBuilder) 229 { 230 this.Ldarg((ArgBuilder)obj); 231 } 232 else if (obj is LocalBuilder) 233 { 234 this.Ldloc((LocalBuilder)obj); 235 } 236 else 237 { 238 this.Ldc(obj); 239 } 240 } 241 242 /// <summary> 243 /// LoadAddress 244 /// </summary> 245 /// <param name="obj"></param> 246 public void LoadAddress(object obj) 247 { 248 if (obj is ArgBuilder) 249 { 250 this.LdargAddress((ArgBuilder)obj); 251 } 252 else if (obj is LocalBuilder) 253 { 254 this.LdlocAddress((LocalBuilder)obj); 255 } 256 else 257 { 258 this.Load(obj); 259 } 260 } 261 262 /// <summary> 263 /// LoadArrayElement 264 /// </summary> 265 /// <param name="obj"></param> 266 /// <param name="arrayIndex"></param> 267 public void LoadArrayElement(object obj, object arrayIndex) 268 { 269 Type objType = this.GetVariableType(obj).GetElementType(); 270 this.Load(obj); 271 this.Load(arrayIndex); 272 if (IsStruct(objType)) 273 { //Stuct类型:先加载地址,然后寻址加载 274 this.Ldelema(objType); 275 this.Ldobj(objType); 276 } 277 else 278 { 279 this.Ldelem(objType); 280 } 281 } 282 283 /// <summary> 284 /// LoadDefaultValue 285 /// </summary> 286 /// <param name="type"></param> 287 public void LoadDefaultValue(Type type) 288 { 289 Check.Require(type, "type"); 290 291 if (!type.IsValueType) 292 { 293 this.Load(null); 294 } 295 else 296 { 297 switch (Type.GetTypeCode(type)) 298 { 299 case TypeCode.Boolean: 300 this.Ldc(false); 301 return; 302 303 case TypeCode.Char: 304 case TypeCode.SByte: 305 case TypeCode.Byte: 306 case TypeCode.Int16: 307 case TypeCode.UInt16: 308 case TypeCode.Int32: 309 case TypeCode.UInt32: 310 this.Ldc(0); 311 return; 312 313 case TypeCode.Int64: 314 case TypeCode.UInt64: 315 this.Ldc((long)0); 316 return; 317 318 case TypeCode.Single: 319 this.Ldc((float)0f); 320 return; 321 322 case TypeCode.Double: 323 this.Ldc((double)0); 324 return; 325 } 326 //非原始类型,一般指结构体Struct 327 LocalBuilder builder = this.DeclareLocal(type, "zero"); 328 this.LoadAddress(builder); 329 this.InitObj(type); 330 this.Load(builder); 331 } 332 } 333 334 /// <summary> 335 /// LoadMember 336 /// Return:执行后的栈顶类型 337 /// </summary> 338 /// <param name="memberInfo"></param> 339 /// <returns></returns> 340 public Type LoadMember(MemberInfo memberInfo) 341 { 342 Check.Require(memberInfo, "memberInfo"); 343 344 Type stackTopType = null; 345 if (memberInfo.MemberType == MemberTypes.Field) 346 { 347 FieldInfo field = (FieldInfo)memberInfo; 348 stackTopType = field.FieldType; 349 if (field.IsStatic) 350 { 351 this.ilGen.Emit(OpCodes.Ldsfld, field); 352 } 353 else 354 { 355 this.ilGen.Emit(OpCodes.Ldfld, field); 356 } 357 } 358 else if (memberInfo.MemberType == MemberTypes.Property) 359 { 360 PropertyInfo info2 = memberInfo as PropertyInfo; 361 stackTopType = info2.PropertyType; 362 if (info2 != null) 363 { 364 MethodInfo methodInfo = info2.GetGetMethod(true); 365 if (methodInfo == null) 366 { 367 throw new Exception("NoGetMethodForProperty"); 368 } 369 this.Call(methodInfo); 370 } 371 } 372 else 373 { 374 if (memberInfo.MemberType != MemberTypes.Method) 375 { 376 throw new Exception("CannotLoadMemberType"); 377 } 378 MethodInfo info4 = (MethodInfo)memberInfo; 379 stackTopType = info4.ReturnType; 380 this.Call(info4); 381 } 382 return stackTopType; 383 } 384 385 /// <summary> 386 /// LoadParam:加载一个参数:加载对象,并转换为方法中参数的类型 387 /// </summary> 388 /// <param name="arg"></param> 389 /// <param name="oneBasedArgIndex"></param> 390 /// <param name="methodInfo"></param> 391 private void LoadParam(object arg, int oneBasedArgIndex, MethodBase methodInfo) 392 { 393 this.Load(arg); 394 if (arg != null) 395 { 396 this.ConvertValue(this.GetVariableType(arg), methodInfo.GetParameters()[oneBasedArgIndex - 1].ParameterType); 397 } 398 } 399 400 /// <summary> 401 /// LoadThis:加载对象,并转换为 402 /// </summary> 403 /// <param name="thisObj"></param> 404 /// <param name="methodInfo"></param> 405 private void LoadThis(object thisObj, MethodInfo methodInfo) 406 { 407 if ((thisObj != null) && !methodInfo.IsStatic) 408 { 409 this.LoadAddress(thisObj); 410 this.ConvertAddress(this.GetVariableType(thisObj), methodInfo.DeclaringType); 411 } 412 }
加载 [参数||参数地址]
1 /// <summary> 2 /// Ldarg 加载第solt参数到堆栈 3 /// 注意:实例方法都有一个隐含参数,也就是第0个参数是表示当前对象引用 也就是 this指针 4 /// </summary> 5 /// <param name="slot">The slot.</param> 6 public void Ldarg(int slot) 7 { 8 switch (slot) 9 { 10 case 0: 11 this.ilGen.Emit(OpCodes.Ldarg_0); 12 return; 13 14 case 1: 15 this.ilGen.Emit(OpCodes.Ldarg_1); 16 return; 17 18 case 2: 19 this.ilGen.Emit(OpCodes.Ldarg_2); 20 return; 21 22 case 3: 23 this.ilGen.Emit(OpCodes.Ldarg_3); 24 return; 25 } 26 if (slot <= 0xff) 27 { 28 //将参数(由指定的短格式索引引用)加载到计算堆栈上。 29 this.ilGen.Emit(OpCodes.Ldarg_S, slot); 30 } 31 else 32 { 33 this.ilGen.Emit(OpCodes.Ldarg, slot); 34 } 35 } 36 37 /// <summary> 38 /// Ldarg 调用Ldarg(int)的重载方式 39 /// </summary> 40 /// <param name="arg"></param> 41 public void Ldarg(ArgBuilder arg) 42 { 43 Check.Require(arg, "arg"); 44 45 this.Ldarg(arg.Index); 46 } 47 48 /// <summary> 49 /// Ldarga 将参数的地址加载到计算堆栈=>注意是加载地址 50 /// 自动判断是使用Ldarga_S,还是Ldarga 51 /// Ldarga_S 指令是用于slot值在 0 到 255的参数编号,效率更高的编码 52 /// </summary> 53 /// <param name="slot"></param> 54 public void Ldarga(int slot) 55 { 56 if (slot <= 0xff) 57 { 58 this.ilGen.Emit(OpCodes.Ldarga_S, slot); 59 } 60 else 61 { 62 this.ilGen.Emit(OpCodes.Ldarga, slot); 63 } 64 } 65 66 /// <summary> 67 /// Ldarga 调用 Ldarga(int) 重载 68 /// </summary> 69 /// <param name="argBuilder"></param> 70 public void Ldarga(ArgBuilder argBuilder) 71 { 72 Check.Require(argBuilder, "argBuilder"); 73 74 this.Ldarga(argBuilder.Index); 75 }
类型方面:
创建构建
1 /// <summary> 2 /// InitObj:初始化值类型 3 /// Pre1: 将要初始化的值类型的地址推送到堆栈上。 4 /// TODO: 从堆栈中弹出地址;将位于指定地址的值类型初始化为 typeTok 类型。 5 /// 提示: 与 Newobj 不同,initobj 不会调用构造函数方法。 Initobj 用于初始化值类型,而 newobj 用于分配和初始化对象。 6 /// </summary> 7 /// <param name="valueType"></param> 8 public void InitObj(Type valueType) 9 { 10 Check.Require(valueType, "valueType"); 11 12 this.ilGen.Emit(OpCodes.Initobj, valueType); 13 } 14 15 16 /// <summary> 17 /// New:初始化引用类型 18 /// </summary> 19 /// <param name="constructorInfo"></param> 20 public void New(ConstructorInfo constructorInfo) 21 { 22 Check.Require(constructorInfo, "constructorInfo"); 23 //Pre1:将从 arg1 到 argn 的参数按顺序推送到堆栈上。 24 //Do1:从堆栈中弹出从 argn 到 arg1 的参数并将它们传递到 ctor 以用于对象创建。 25 //Do2:将对新对象的引用推送到堆栈上。 26 this.ilGen.Emit(OpCodes.Newobj, constructorInfo); 27 } 28 29 /// <summary> 30 /// New:带一个参数的构建方法 31 /// </summary> 32 /// <param name="constructorInfo"></param> 33 /// <param name="param1"></param> 34 public void New(ConstructorInfo constructorInfo, object param1) 35 { 36 Check.Require(constructorInfo, "constructorInfo"); 37 38 this.LoadParam(param1, 1, constructorInfo); 39 this.New(constructorInfo); 40 } 41 42 /// <summary> 43 /// NewArray:构造数组 44 /// </summary> 45 /// <param name="elementType"></param> 46 /// <param name="len"></param> 47 public void NewArray(Type elementType, object len) 48 { 49 Check.Require(elementType, "elementType"); 50 51 this.Load(len); 52 this.ilGen.Emit(OpCodes.Newarr, elementType); 53 }
类型转换
1 /// <summary> 2 /// InternalConvert: 3 /// </summary> 4 /// <param name="source"></param> 5 /// <param name="target"></param> 6 /// <param name="isAddress"></param> 7 private void InternalConvert(Type source, Type target, bool isAddress) 8 { 9 if (target != source) 10 { 11 if (target.IsValueType) 12 { //都为值类型 13 if (source.IsValueType) 14 { 15 OpCode opcode = this.GetConvOpCode(Type.GetTypeCode(target)); 16 if (opcode.Equals(OpCodes.Nop)) 17 { 18 throw new Exception("NoConversionPossible"); 19 } 20 this.ilGen.Emit(opcode); 21 } 22 else 23 { 24 if (!source.IsAssignableFrom(target)) 25 { 26 throw new Exception("IsNotAssignableFrom"); 27 } 28 //source引用类型 变为target值类型 29 this.Unbox(target); 30 if (!isAddress) 31 { 32 this.Ldobj(target); 33 } 34 } 35 } 36 //target=source; source继承于target==>target,source都是引用类型 37 else if (target.IsAssignableFrom(source)) 38 { 39 if (source.IsValueType) 40 { //栈顶是source对象的地址 41 if (isAddress) 42 { 43 this.Ldobj(source); 44 } 45 this.Box(source); 46 } 47 } 48 //source=target;target继承于source 49 else if (source.IsAssignableFrom(target)) 50 { 51 this.Castclass(target); 52 } 53 else 54 { 55 if (!target.IsInterface && !source.IsInterface) 56 { 57 throw new Exception("IsNotAssignableFrom"); 58 } 59 this.Castclass(target); 60 } 61 } 62 } 63 64 /// <summary> 65 /// ConvertAddress 66 /// </summary> 67 /// <param name="source"></param> 68 /// <param name="target"></param> 69 public void ConvertAddress(Type source, Type target) 70 { 71 Check.Require(source, "source"); 72 Check.Require(target, "target"); 73 74 this.InternalConvert(source, target, true); 75 } 76 77 /// <summary> 78 /// ConvertValue 79 /// </summary> 80 /// <param name="source"></param> 81 /// <param name="target"></param> 82 public void ConvertValue(Type source, Type target) 83 { 84 Check.Require(source, "source"); 85 Check.Require(target, "target"); 86 87 this.InternalConvert(source, target, false); 88 } 89 90 91 /// <summary> 92 /// Castclass 93 /// </summary> 94 /// <param name="target"></param> 95 public void Castclass(Type target) 96 { 97 Check.Require(target, "target"); 98 99 this.ilGen.Emit(OpCodes.Castclass, target); 100 } 101 102 /// <summary> 103 /// Box 104 /// </summary> 105 /// <param name="type"></param> 106 public void Box(Type type) 107 { 108 Check.Require(type, "type"); 109 Check.Require(type.IsValueType, "type MUST be ValueType"); 110 111 this.ilGen.Emit(OpCodes.Box, type); 112 } 113 114 /// <summary> 115 /// Unbox 116 /// </summary> 117 /// <param name="type"></param> 118 public void Unbox(Type type) 119 { 120 Check.Require(type, "type"); 121 Check.Require(type.IsValueType, "type MUST be ValueType"); 122 //pre: 将对象引用推送到堆栈上 123 //Do1: 从堆栈中弹出对象引用并取消装箱为值类型指针 124 //Do2: 将值类型指针推送到堆栈上 125 //Result:栈顶保存值类型的指针 126 this.ilGen.Emit(OpCodes.Unbox, type); 127 //如果需将值加载到堆栈上=>ldobj 128 //Pre:将值类型对象的地址推送到地址上。 129 //Do1:从堆栈中弹出该地址并查找位于该特定地址处的实例。 130 //Do2:将存储在该地址处的对象的值推送到堆栈上。 131 } 132 133 /// <summary> 134 /// UnboxAny 135 /// 当应用于值类型的已装箱形式时,unbox.any 指令提取 obj(类型为 O)中包含的值,因此等效于 unbox 后跟 ldobj。 136 /// 当应用于引用类型时,unbox.any 指令与 castclass 效果相同。 137 /// </summary> 138 /// <param name="type"></param> 139 public void UnboxAny(Type type) 140 { 141 Check.Require(type, "type"); 142 Check.Require(type.IsValueType, "type MUST be ValueType"); 143 //Pre: 将对象引用 obj 推送到堆栈上 144 //Do1: 从堆栈中弹出对象引用,取消装箱到指令中指定的类型 145 //Do2: 将结果对象引用或值类型推送到堆栈上 146 //Result:栈顶保存值类型的值 147 this.ilGen.Emit(OpCodes.Unbox_Any, type); 148 149 //castclass 指令 150 // 将对象引用推送到堆栈上 151 // 从堆栈中弹出对象引用;引用的对象被转换为指定的 class 152 // 如果成功,则新对象引用被推送到堆栈上 153 }
运算符:
算式运算符
1 /// <summary> 2 /// Add 3 /// </summary> 4 public void Add() 5 { 6 this.ilGen.Emit(OpCodes.Add); 7 } 8 /// <summary> 9 /// Inc 10 /// </summary> 11 /// <param name="var"></param> 12 public void Inc(object var) 13 { 14 this.Load(var); 15 this.Load(1); 16 this.Add(); 17 this.Store(var); 18 } 19 /// <summary> 20 /// Dec 21 /// </summary> 22 /// <param name="var"></param> 23 public void Dec(object var) 24 { 25 this.Load(var); 26 this.Load(1); 27 this.Subtract(); 28 this.Store(var); 29 } 30 /// <summary> 31 /// Subtract 32 /// </summary> 33 public void Subtract() 34 { 35 this.ilGen.Emit(OpCodes.Sub); 36 }
位运算符
1 /// <summary> 2 /// And 3 /// </summary> 4 public void And() 5 { 6 this.ilGen.Emit(OpCodes.And); 7 } 8 /// <summary> 9 /// Not 10 /// </summary> 11 public void Not() 12 { 13 this.ilGen.Emit(OpCodes.Not); 14 } 15 16 /// <summary> 17 /// Or 18 /// </summary> 19 public void Or() 20 { 21 this.ilGen.Emit(OpCodes.Or); 22 }
关系运算符
1 /// <summary> 2 /// Ceq 3 /// </summary> 4 public void Ceq() 5 { 6 this.ilGen.Emit(OpCodes.Ceq); 7 }
公共操作:
指令获取
1 private OpCode GetBranchCode(Cmp cmp) 2 { 3 switch (cmp) 4 { 5 case Cmp.LessThan: 6 return OpCodes.Bge; 7 8 case Cmp.EqualTo: 9 return OpCodes.Bne_Un; 10 11 case Cmp.LessThanOrEqualTo: 12 return OpCodes.Bgt; 13 14 case Cmp.GreaterThan: 15 return OpCodes.Ble; 16 17 case Cmp.NotEqualTo: 18 return OpCodes.Beq; 19 } 20 return OpCodes.Blt; 21 } 22 23 //相反的比较关系 24 private Cmp GetCmpInverse(Cmp cmp) 25 { 26 switch (cmp) 27 { 28 case Cmp.LessThan: 29 return Cmp.GreaterThanOrEqualTo; 30 31 case Cmp.EqualTo: 32 return Cmp.NotEqualTo; 33 34 case Cmp.LessThanOrEqualTo: 35 return Cmp.GreaterThan; 36 37 case Cmp.GreaterThan: 38 return Cmp.LessThanOrEqualTo; 39 40 case Cmp.NotEqualTo: 41 return Cmp.EqualTo; 42 } 43 return Cmp.LessThan; 44 } 45 46 private OpCode GetConvOpCode(TypeCode typeCode) 47 { 48 switch (typeCode) 49 { 50 case TypeCode.Boolean: 51 //Pre:value 被推送到堆栈上。 52 //Do1:从堆栈中弹出 value,然后尝试执行转换操作。 53 //Do2:如果转换成功,则将结果值推送到堆栈上。 54 return OpCodes.Conv_I1; 55 56 case TypeCode.Char: 57 return OpCodes.Conv_I2; 58 59 case TypeCode.SByte: 60 return OpCodes.Conv_I1; 61 62 case TypeCode.Byte: 63 return OpCodes.Conv_U1; 64 65 case TypeCode.Int16: 66 return OpCodes.Conv_I2; 67 68 case TypeCode.UInt16: 69 return OpCodes.Conv_U2; 70 71 case TypeCode.Int32: 72 return OpCodes.Conv_I4; 73 74 case TypeCode.UInt32: 75 return OpCodes.Conv_U4; 76 77 case TypeCode.Int64: 78 return OpCodes.Conv_I8; 79 80 case TypeCode.UInt64: 81 return OpCodes.Conv_I8; 82 83 case TypeCode.Single: 84 return OpCodes.Conv_R4; 85 86 case TypeCode.Double: 87 return OpCodes.Conv_R8; 88 } 89 return OpCodes.Nop; 90 } 91 92 private OpCode GetLdelemOpCode(TypeCode typeCode) 93 { 94 switch (typeCode) 95 { 96 case TypeCode.Object: 97 case TypeCode.DBNull: 98 return OpCodes.Ldelem_Ref; 99 100 case TypeCode.Boolean: 101 return OpCodes.Ldelem_I1; 102 103 case TypeCode.Char: 104 return OpCodes.Ldelem_I2; 105 106 case TypeCode.SByte: 107 return OpCodes.Ldelem_I1; 108 109 case TypeCode.Byte: 110 return OpCodes.Ldelem_U1; 111 112 case TypeCode.Int16: 113 //Pre1:将对象引用 array 推送到堆栈上。 114 //Pre2:将索引值 index 推送到堆栈上。 115 //Do1:从堆栈中弹出 index 和 array;查找存储在 array 中的位置 index 处的值。 116 //Do2:将值推送到堆栈上。 117 return OpCodes.Ldelem_I2; 118 119 case TypeCode.UInt16: 120 return OpCodes.Ldelem_U2; 121 122 case TypeCode.Int32: 123 return OpCodes.Ldelem_I4; 124 125 case TypeCode.UInt32: 126 return OpCodes.Ldelem_U4; 127 128 case TypeCode.Int64: 129 return OpCodes.Ldelem_I8; 130 131 case TypeCode.UInt64: 132 return OpCodes.Ldelem_I8; 133 134 case TypeCode.Single: 135 return OpCodes.Ldelem_R4; 136 137 case TypeCode.Double: 138 return OpCodes.Ldelem_R8; 139 140 case TypeCode.String: 141 return OpCodes.Ldelem_Ref; 142 } 143 return OpCodes.Nop; 144 } 145 146 /// <summary> 147 /// 根据值类型,返回使用哪个指令将值类型复制到计算堆栈上(ldobj指令的功能) 148 /// 间址寻址 取数 149 /// 所有 ldind 指令都是指定相应内置值类的 Ldobj 指令的快捷方式 150 /// </summary> 151 /// <param name="typeCode">The type code.</param> 152 /// <returns></returns> 153 private OpCode GetLdindOpCode(TypeCode typeCode) 154 { 155 switch (typeCode) 156 { 157 case TypeCode.Boolean: 158 //将 int8 类型的值作为 int32 间接加载到计算堆栈上。 159 //也就是:将位于栈顶的地址,所对应的int8,作为int32加载到堆栈上。 160 161 return OpCodes.Ldind_I1; 162 163 case TypeCode.Char: 164 return OpCodes.Ldind_I2; 165 166 case TypeCode.SByte: 167 return OpCodes.Ldind_I1; 168 169 case TypeCode.Byte: 170 return OpCodes.Ldind_U1; 171 172 case TypeCode.Int16: 173 return OpCodes.Ldind_I2; 174 175 case TypeCode.UInt16: 176 return OpCodes.Ldind_U2; 177 178 case TypeCode.Int32: 179 return OpCodes.Ldind_I4; 180 181 case TypeCode.UInt32: 182 return OpCodes.Ldind_U4; 183 //请注意,小于 4 个字节的整数值在加载到计算堆栈上时会被扩展为 int32 184 // 185 case TypeCode.Int64: 186 return OpCodes.Ldind_I8; 187 188 case TypeCode.UInt64: 189 return OpCodes.Ldind_I8; 190 191 case TypeCode.Single: 192 return OpCodes.Ldind_R4; 193 194 case TypeCode.Double: 195 return OpCodes.Ldind_R8; 196 197 case TypeCode.String: 198 //将地址 addr 处的对象引用作为 O 类型加载到堆栈上 199 return OpCodes.Ldind_Ref; 200 } 201 return OpCodes.Nop; 202 } 203 204 private OpCode GetStelemOpCode(TypeCode typeCode) 205 { 206 switch (typeCode) 207 { 208 case TypeCode.Object: 209 case TypeCode.DBNull: 210 //用计算堆栈上的对象 ref 值(O 类型)替换给定索引处的数组元素。 211 return OpCodes.Stelem_Ref; 212 213 case TypeCode.Boolean: 214 return OpCodes.Stelem_I1; 215 216 case TypeCode.Char: 217 return OpCodes.Stelem_I2; 218 219 case TypeCode.SByte: 220 return OpCodes.Stelem_I1; 221 222 case TypeCode.Byte: 223 return OpCodes.Stelem_I1; 224 225 case TypeCode.Int16: 226 return OpCodes.Stelem_I2; 227 228 case TypeCode.UInt16: 229 //How:用计算堆栈上的 int16 值替换给定索引处的数组元素。 230 //Pre1: 将对数组 array 的对象引用推送到堆栈上。 231 //Pre2: 将array 中元素的有效索引推送到堆栈上。 232 //Pre3:将值推送到堆栈上。 233 //ToDo: 从堆栈中弹出值、索引和数组引用;将值放入给定索引处的数组元素中。 234 return OpCodes.Stelem_I2; 235 236 case TypeCode.Int32: 237 return OpCodes.Stelem_I4; 238 239 case TypeCode.UInt32: 240 return OpCodes.Stelem_I4; 241 242 case TypeCode.Int64: 243 return OpCodes.Stelem_I8; 244 245 case TypeCode.UInt64: 246 return OpCodes.Stelem_I8; 247 248 case TypeCode.Single: 249 return OpCodes.Stelem_R4; 250 251 case TypeCode.Double: 252 return OpCodes.Stelem_R8; 253 254 case TypeCode.String: 255 return OpCodes.Stelem_Ref; 256 } 257 return OpCodes.Nop; 258 }
常用方法
1 /// <summary> 2 /// DefineLabel 3 /// </summary> 4 /// <returns></returns> 5 public Label DefineLabel() 6 { 7 return this.ilGen.DefineLabel(); 8 } 9 10 /// <summary> 11 /// MarkLabel 12 /// </summary> 13 /// <param name="label"></param> 14 public void MarkLabel(Label label) 15 { 16 //不能多次定义一个标签 17 this.ilGen.MarkLabel(label); 18 } 19 20 /// <summary> 21 /// Dup:对堆栈顶部的数据 进行拷贝 22 /// </summary> 23 public void Dup() 24 { 25 this.ilGen.Emit(OpCodes.Dup); 26 } 27 28 29 /// <summary> 30 /// GetArg 31 /// </summary> 32 /// <param name="index"></param> 33 /// <returns></returns> 34 public ArgBuilder GetArg(int index) 35 { 36 return (ArgBuilder)this.argList[index]; 37 } 38 39 /// <summary> 40 /// GetVariableType 41 /// </summary> 42 /// <param name="var"></param> 43 /// <returns></returns> 44 public Type GetVariableType(object var) 45 { 46 if (var is ArgBuilder) 47 { 48 return ((ArgBuilder)var).ArgType; 49 } 50 if (var is LocalBuilder) 51 { 52 return ((LocalBuilder)var).LocalType; 53 } 54 return var.GetType(); 55 } 56 57 private static bool IsStruct(Type objType) 58 { 59 if (objType.IsValueType) 60 { 61 return !objType.IsPrimitive; //非原始的数值类型:也就是非int,long,bool等类型 62 } 63 return false; 64 } 65 66 67 /// <summary> 68 /// Pop:两个指令集有何区别 69 /// a=GetAge(); 70 /// GetAge(); 71 /// 前者需要将栈顶的值弹入a中,后者从栈顶弹出不保存 72 /// 前者是一个保存操作,后者即是Pop操作 73 /// </summary> 74 public void Pop() 75 { 76 this.ilGen.Emit(OpCodes.Pop); 77 } 78 79 /// <summary> 80 /// Throw 81 /// </summary> 82 public void Throw() 83 { 84 this.ilGen.Emit(OpCodes.Throw); 85 } 86 87 private void ThrowMismatchException(object expected) 88 { 89 throw new Exception("ExpectingEnd"); 90 }
结构语句:
条件跳转
1 /// <summary> 2 /// Bgt 3 /// </summary> 4 /// <param name="label"></param> 5 public void Bgt(Label label) 6 { 7 this.ilGen.Emit(OpCodes.Bgt, label); 8 } 9 10 /// <summary> 11 /// Ble 12 /// </summary> 13 /// <param name="label"></param> 14 public void Ble(Label label) 15 { 16 this.ilGen.Emit(OpCodes.Ble, label); 17 } 18 19 /// <summary> 20 /// Blt 21 /// </summary> 22 /// <param name="label"></param> 23 public void Blt(Label label) 24 { 25 this.ilGen.Emit(OpCodes.Blt, label); 26 } 27 28 /// <summary> 29 /// Br 无条件地将控制转移到目标指令 30 /// </summary> 31 /// <param name="label"></param> 32 public void Br(Label label) 33 { 34 this.ilGen.Emit(OpCodes.Br, label); 35 } 36 37 /// <summary> 38 /// Brfalse 39 /// </summary> 40 /// <param name="label"></param> 41 public void Brfalse(Label label) 42 { 43 this.ilGen.Emit(OpCodes.Brfalse, label); 44 } 45 46 /// <summary> 47 /// Brtrue 48 /// </summary> 49 /// <param name="label"></param> 50 public void Brtrue(Label label) 51 { 52 this.ilGen.Emit(OpCodes.Brtrue, label); 53 }
If语句
1 /// <summary> 2 /// If 3 /// </summary> 4 /// <param name="value1"></param> 5 /// <param name="cmpOp"></param> 6 /// <param name="value2"></param> 7 public void If(object value1, Cmp cmpOp, object value2) 8 { 9 this.Load(value1); 10 this.Load(value2); 11 this.If(cmpOp); 12 } 13 14 /// <summary> 15 /// If 16 /// </summary> 17 /// <param name="cmpOp"></param> 18 public void If(Cmp cmpOp) 19 { 20 //if(a==b){ } 21 IfState state = new IfState(); 22 state.EndIf = this.DefineLabel(); 23 state.ElseBegin = this.DefineLabel(); 24 this.ilGen.Emit(this.GetBranchCode(cmpOp), state.ElseBegin); 25 this.blockStack.Push(state); 26 } 27 /// <summary> 28 /// ElseIf 29 /// </summary> 30 /// <param name="value1"></param> 31 /// <param name="cmpOp"></param> 32 /// <param name="value2"></param> 33 public void ElseIf(object value1, Cmp cmpOp, object value2) 34 { 35 IfState state = (IfState)this.blockStack.Pop(); 36 this.Br(state.EndIf); 37 this.MarkLabel(state.ElseBegin); 38 this.Load(value1); 39 this.Load(value2); 40 state.ElseBegin = this.DefineLabel(); 41 this.ilGen.Emit(this.GetBranchCode(cmpOp), state.ElseBegin); 42 this.blockStack.Push(state); 43 } 44 45 46 /// <summary> 47 /// Else 48 /// </summary> 49 public void Else() 50 { 51 IfState state = this.PopIfState(); 52 this.Br(state.EndIf); 53 this.MarkLabel(state.ElseBegin); 54 state.ElseBegin = state.EndIf; 55 this.blockStack.Push(state); 56 } 57 58 59 /// <summary> 60 /// EndIf 61 /// </summary> 62 public void EndIf() 63 { 64 IfState state = this.PopIfState(); 65 if (!state.ElseBegin.Equals(state.EndIf)) 66 { 67 this.MarkLabel(state.ElseBegin); 68 } 69 this.MarkLabel(state.EndIf); 70 } 71 72 73 74 75 76 /// <summary> 77 /// If 78 /// </summary> 79 public void If() 80 { 81 this.InternalIf(false); 82 } 83 /// <summary> 84 /// IfNot 85 /// </summary> 86 public void IfNot() 87 { 88 this.InternalIf(true); 89 } 90 private void InternalIf(bool negate) 91 { 92 IfState state = new IfState(); 93 state.EndIf = this.DefineLabel(); 94 state.ElseBegin = this.DefineLabel(); 95 if (negate) 96 { 97 this.Brtrue(state.ElseBegin); 98 } 99 else 100 { 101 this.Brfalse(state.ElseBegin); 102 } 103 this.blockStack.Push(state); 104 } 105 106 107 108 /// <summary> 109 /// IfNotDefaultValue 110 /// </summary> 111 /// <param name="value"></param> 112 public void IfNotDefaultValue(object value) 113 { 114 Type variableType = this.GetVariableType(value); 115 TypeCode typeCode = Type.GetTypeCode(variableType); 116 if (((typeCode == TypeCode.Object) && variableType.IsValueType) || ((typeCode == TypeCode.DateTime) || (typeCode == TypeCode.Decimal))) 117 { 118 this.LoadDefaultValue(variableType); 119 this.ConvertValue(variableType, typeof(object)); 120 this.Load(value); 121 this.ConvertValue(variableType, typeof(object)); 122 this.Call(ObjectEquals); 123 this.IfNot(); 124 } 125 else 126 { 127 this.LoadDefaultValue(variableType); 128 this.Load(value); 129 this.If(Cmp.NotEqualTo); 130 } 131 } 132 133 private IfState PopIfState() 134 { 135 object expected = this.blockStack.Pop(); 136 IfState state = expected as IfState; 137 if (state == null) 138 { 139 this.ThrowMismatchException(expected); 140 } 141 return state; 142 }
If语句示意[有Else]
1 // if(...) Goto BeginIf 2 3 ////{IfCode} 4 5 // Goto EndIf 6 //:BeginIf 7 // if(...) Goto ElseIf1 8 9 ////{Else-IfCode} 10 11 // Goto Endif 12 //:ElseIf1 13 // if(...) Goto ElseIf2 14 15 ////{ElseCode} 16 17 ////注:(ElseIf2==EndIf),差异是无ElseIf2 18 //:EndIf
If语句示意[无Else]
1 // if(...) Goto BeginIf 2 3 //{If-Code} 4 5 // Goto EndIf 6 //:BeginIf 7 // if(...) Goto ElseIf1 8 9 //{Else-IfCode} 10 11 // Goto Endif 12 //:ElseIf1 13 // if(...) Goto ElseIf2 14 15 //{Else-IfCode} 16 17 //:ElseIf2 18 //:EndIf
Switch语句
1 /// <summary> 2 /// Switch 3 /// </summary> 4 /// <param name="labelCount"></param> 5 /// <returns></returns> 6 public Label[] Switch(int labelCount) 7 { 8 SwitchState state = new SwitchState(this.DefineLabel(), this.DefineLabel()); 9 Label[] labels = new Label[labelCount]; 10 for (int i = 0; i < labels.Length; i++) 11 { 12 labels[i] = this.DefineLabel(); 13 } 14 this.ilGen.Emit(OpCodes.Switch, labels); 15 this.Br(state.DefaultLabel); 16 this.blockStack.Push(state); 17 return labels; 18 } 19 20 21 /// <summary> 22 /// Case 23 /// </summary> 24 /// <param name="caseLabel1"></param> 25 /// <param name="caseLabelName"></param> 26 public void Case(Label caseLabel1, string caseLabelName) 27 { 28 this.MarkLabel(caseLabel1); 29 } 30 /// <summary> 31 /// DefaultCase:开始default代码块 32 /// </summary> 33 public void DefaultCase() 34 { 35 object expected = this.blockStack.Peek(); 36 SwitchState state = expected as SwitchState; 37 if (state == null) 38 { 39 this.ThrowMismatchException(expected); 40 } 41 this.MarkLabel(state.DefaultLabel); 42 state.DefaultDefined = true; 43 } 44 45 46 /// <summary> 47 /// EndCase:相当于Switch中的break 48 /// </summary> 49 public void EndCase() 50 { 51 object expected = this.blockStack.Peek(); 52 SwitchState state = expected as SwitchState; 53 if (state == null) 54 { 55 this.ThrowMismatchException(expected); 56 } 57 this.Br(state.EndOfSwitchLabel); 58 } 59 /// <summary> 60 /// EndSwitch 61 /// </summary> 62 public void EndSwitch() 63 { 64 object expected = this.blockStack.Pop(); 65 SwitchState state = expected as SwitchState; 66 if (state == null) 67 { 68 this.ThrowMismatchException(expected); 69 } 70 if (!state.DefaultDefined) 71 { 72 this.MarkLabel(state.DefaultLabel); 73 } 74 this.MarkLabel(state.EndOfSwitchLabel); 75 }
For||Foreach
1 /// <summary> 2 /// For 3 /// </summary> 4 /// <param name="local"></param> 5 /// <param name="start"></param> 6 /// <param name="end"></param> 7 /// <returns></returns> 8 public object For(LocalBuilder local, object start, object end) 9 { 10 Check.Require(local, "local"); 11 12 ForState state = new ForState(local, this.DefineLabel(), this.DefineLabel(), end); 13 if (state.Index != null) 14 { 15 this.Load(start); 16 this.Stloc(state.Index); 17 this.Br(state.TestLabel); 18 } 19 this.MarkLabel(state.BeginLabel); 20 this.blockStack.Push(state); 21 return state; 22 } 23 // Index=start; 24 // Begin: 25 // 26 // Index++; 27 // Test: 28 // if(Index<N) goto :Begin 29 // 30 // End: 31 /// <summary> 32 /// EndFor 33 /// </summary> 34 public void EndFor() 35 { 36 object expected = this.blockStack.Pop(); 37 ForState state = expected as ForState; 38 if (state == null) 39 { 40 this.ThrowMismatchException(expected); 41 } 42 if (state.Index != null) 43 { 44 //Inc: Index++ 45 this.Ldloc(state.Index); 46 this.Ldc(1); 47 this.Add(); 48 this.Stloc(state.Index); 49 50 this.MarkLabel(state.TestLabel); 51 52 //if(i<n) goto begin 53 this.Ldloc(state.Index);//加载:局部变量 与 常量的区别 54 //加载Length或循环n 55 this.Load(state.End); 56 if (this.GetVariableType(state.End).IsArray) 57 { 58 this.Ldlen(); 59 } 60 this.Blt(state.BeginLabel); 61 } 62 else 63 { //while(true) 64 this.Br(state.BeginLabel); 65 } 66 //如果需要,则添加End标签 67 if (state.RequiresEndLabel) 68 { 69 this.MarkLabel(state.EndLabel); 70 } 71 } 72 73 74 /// <summary> 75 /// ForEach 76 /// </summary> 77 /// <param name="local">当前元素接受变量</param> 78 /// <param name="elementType">元素类型</param> 79 /// <param name="enumeratorType">enumerator类型</param> 80 /// <param name="enumerator">enumerator实例</param> 81 /// <param name="getCurrentMethod">enumerator类型Getcurrent方法</param> 82 public void ForEach(LocalBuilder local, Type elementType, Type enumeratorType, LocalBuilder enumerator, MethodInfo getCurrentMethod) 83 { 84 Check.Require(local, "local"); 85 Check.Require(elementType, "elementType"); 86 Check.Require(enumeratorType, "enumeratorType"); 87 Check.Require(enumerator, "enumerator"); 88 Check.Require(getCurrentMethod, "getCurrentMethod"); 89 90 ForState state = new ForState(local, this.DefineLabel(), this.DefineLabel(), enumerator); 91 this.Br(state.TestLabel); 92 this.MarkLabel(state.BeginLabel); 93 if (enumeratorType == getCurrentMethod.DeclaringType) 94 { 95 this.LoadThis(enumerator, getCurrentMethod); 96 this.ilGen.Emit(OpCodes.Call, getCurrentMethod); 97 } 98 else 99 { 100 this.Call(enumerator, getCurrentMethod); 101 } 102 this.ConvertValue(elementType, this.GetVariableType(local)); 103 this.Stloc(local); 104 this.blockStack.Push(state); 105 } 106 107 // Goto Test 108 //Begin: 109 // local=(elementType)GetCurrent() 110 ///// [ForCode] 111 //:Test 112 // if(MoveNext()==true) Goto Begin 113 //:End 114 115 /// <summary> 116 /// EndForEach 117 /// </summary> 118 /// <param name="moveNextMethod"></param> 119 public void EndForEach(MethodInfo moveNextMethod) 120 { 121 Check.Require(moveNextMethod, "moveNextMethod"); 122 123 object expected = this.blockStack.Pop(); 124 ForState state = expected as ForState; 125 if (state == null) 126 { 127 this.ThrowMismatchException(expected); 128 } 129 this.MarkLabel(state.TestLabel); 130 object var = state.End; 131 if (this.GetVariableType(var) == moveNextMethod.DeclaringType) 132 { 133 this.LoadThis(var, moveNextMethod); 134 this.ilGen.Emit(OpCodes.Call, moveNextMethod); 135 } 136 else 137 { 138 this.Call(var, moveNextMethod); 139 } 140 this.Brtrue(state.BeginLabel); 141 if (state.RequiresEndLabel) 142 { 143 this.MarkLabel(state.EndLabel); 144 } 145 } 146 147 148 /// <summary> 149 /// Break 150 /// </summary> 151 /// <param name="forState"></param> 152 public void Break(object forState) 153 { 154 this.InternalBreakFor(forState, OpCodes.Br); 155 } 156 157 /// <summary> 158 /// IfTrueBreak 159 /// </summary> 160 /// <param name="forState"></param> 161 public void IfTrueBreak(object forState) 162 { 163 this.InternalBreakFor(forState, OpCodes.Brtrue); 164 } 165 166 /// <summary> 167 /// IfFalseBreak 168 /// </summary> 169 /// <param name="forState"></param> 170 public void IfFalseBreak(object forState) 171 { 172 this.InternalBreakFor(forState, OpCodes.Brfalse); 173 } 174 175 176 /// <summary> 177 /// InternalBreakFor:Break 178 /// </summary> 179 /// <param name="userForState"></param> 180 /// <param name="branchInstruction"></param> 181 public void InternalBreakFor(object userForState, OpCode branchInstruction) 182 { 183 foreach (object obj2 in this.blockStack) 184 { 185 ForState state = obj2 as ForState; 186 if ((state != null) && (state == userForState)) 187 { 188 //定义EndLabel 189 if (!state.RequiresEndLabel) 190 { 191 state.EndLabel = this.DefineLabel(); 192 state.RequiresEndLabel = true; 193 } 194 this.ilGen.Emit(branchInstruction, state.EndLabel); 195 break; 196 } 197 } 198 }
方法:
方法定义
1 /// <summary> 2 /// BeginMethod 3 /// </summary> 4 /// <param name="methodName"></param> 5 /// <param name="delegateType"></param> 6 public void BeginMethod(string methodName, Type delegateType) 7 { 8 Check.Require(this.methodOrConstructorBuilder == null, "BeginMethod() could not be called in this context."); 9 Check.Require(methodName, "methodName", Check.NotNullOrEmpty); 10 Check.Require(delegateType, "delegateType"); 11 //通过Invoke方法 来获取参数类型 及返回类型 12 MethodInfo method = delegateType.GetMethod("Invoke"); 13 ParameterInfo[] parameters = method.GetParameters(); 14 Type[] argTypes = new Type[parameters.Length]; 15 for (int i = 0; i < parameters.Length; i++) 16 { 17 argTypes[i] = parameters[i].ParameterType; 18 } 19 this.BeginMethod(method.ReturnType, methodName, argTypes); 20 this.delegateType = delegateType; 21 } 22 23 /// <summary> 24 /// BeginMethod 25 /// </summary> 26 /// <param name="returnType"></param> 27 /// <param name="methodName"></param> 28 /// <param name="argTypes"></param> 29 private void BeginMethod(Type returnType, string methodName, params Type[] argTypes) 30 { 31 //Emit 构建方法的一种 32 //对于定义整个类:可以参考另一种方式 typeBuilder.DefineMethod(targetMethod.Name, MethodAttributes.Public|MethodAttributes.Virtual, targetMethod.ReturnType, paramType); 33 //定义方法体 returnType methodName(argTypes){ } 34 this.dynamicMethod = new DynamicMethod(methodName, returnType, argTypes, serializationModule, true); 35 //获取方法体:写入流 36 this.ilGen = this.dynamicMethod.GetILGenerator();// this.ilGen代表当前方法上下文,所以Ldarg加载的是当前方法的。 在当前类里面,存于this.argList 37 this.methodEndLabel = this.ilGen.DefineLabel(); 38 this.blockStack = new Stack(); 39 this.argList = new ArrayList(); 40 for (int i = 0; i < argTypes.Length; i++) 41 { 42 this.argList.Add(new ArgBuilder(i, argTypes[i])); 43 } 44 } 45 46 47 /// <summary> 48 /// EndMethod 49 /// </summary> 50 /// <returns></returns> 51 public Delegate EndMethod() 52 { 53 Check.Require(this.methodOrConstructorBuilder == null, "EndMethod() could not be called in this context."); 54 //在此之前,通过this.ilGen添加操作代码,最后生成委托 55 56 //要返回的参数,现在在堆栈顶部 57 this.MarkLabel(this.methodEndLabel); 58 this.Ret(); 59 Delegate delegate2 = null; 60 delegate2 = this.dynamicMethod.CreateDelegate(this.delegateType); 61 62 //清空 63 this.dynamicMethod = null; 64 this.delegateType = null; 65 this.ilGen = null; 66 this.blockStack = null; 67 this.argList = null; 68 return delegate2; 69 } 70 71 /// <summary> 72 /// IgnoreReturnValue 73 /// </summary> 74 public void IgnoreReturnValue() 75 { 76 this.Pop(); 77 } 78 79 /// <summary> 80 /// Ret 从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。 81 /// Do1: 从被调用方的计算堆栈中弹出返回值。 82 /// Do2:将步骤 1 中获取的返回值推送到调用方的计算堆栈中。 83 /// </summary> 84 public void Ret() 85 { 86 this.ilGen.Emit(OpCodes.Ret); 87 }
方法调用
1 /// <summary> 2 /// Call 调用由传递的方法说明符指示的方法。 3 /// </summary> 4 /// <param name="ctor"></param> 5 public void Call(ConstructorInfo ctor) 6 { 7 Check.Require(ctor, "ctor"); 8 9 this.ilGen.Emit(OpCodes.Call, ctor); 10 } 11 12 /// <summary> 13 /// Call 调用由传递的方法说明符指示的方法。 14 /// </summary> 15 /// <param name="methodInfo"></param> 16 public void Call(MethodInfo methodInfo) 17 { 18 Check.Require(methodInfo, "methodInfo"); 19 20 if (methodInfo.IsVirtual) 21 { 22 this.ilGen.Emit(OpCodes.Callvirt, methodInfo); 23 } 24 else if (methodInfo.IsStatic) 25 { 26 this.ilGen.Emit(OpCodes.Call, methodInfo); 27 } 28 else 29 { 30 this.ilGen.Emit(OpCodes.Call, methodInfo); 31 } 32 } 33 34 /// <summary> 35 /// Call 36 /// </summary> 37 /// <param name="thisObj"></param> 38 /// <param name="methodInfo"></param> 39 public void Call(object thisObj, MethodInfo methodInfo) 40 { 41 Check.Require(thisObj, "thisObj"); 42 Check.Require(methodInfo, "methodInfo"); 43 44 this.VerifyParameterCount(methodInfo, 0); 45 this.LoadThis(thisObj, methodInfo); 46 this.Call(methodInfo); 47 } 48 49 /// <summary> 50 /// Call 51 /// </summary> 52 /// <param name="thisObj"></param> 53 /// <param name="methodInfo"></param> 54 /// <param name="param1"></param> 55 public void Call(object thisObj, MethodInfo methodInfo, object param1) 56 { 57 Check.Require(thisObj, "thisObj"); 58 Check.Require(methodInfo, "methodInfo"); 59 60 this.VerifyParameterCount(methodInfo, 1); 61 //Loadthis:加载this对象,并且转换为方法声明类的类型 62 this.LoadThis(thisObj, methodInfo); 63 //LoadParam:加载参数,并且转换为方法参数所定义的类型 64 this.LoadParam(param1, 1, methodInfo); 65 this.Call(methodInfo); 66 } 67 68 /// <summary> 69 /// Call 70 /// </summary> 71 /// <param name="thisObj"></param> 72 /// <param name="methodInfo"></param> 73 /// <param name="param1"></param> 74 /// <param name="param2"></param> 75 public void Call(object thisObj, MethodInfo methodInfo, object param1, object param2) 76 { 77 Check.Require(thisObj, "thisObj"); 78 Check.Require(methodInfo, "methodInfo"); 79 80 this.VerifyParameterCount(methodInfo, 2); 81 this.LoadThis(thisObj, methodInfo); 82 this.LoadParam(param1, 1, methodInfo); 83 this.LoadParam(param2, 2, methodInfo); 84 this.Call(methodInfo); 85 } 86 87 /// <summary> 88 /// Call 89 /// </summary> 90 /// <param name="thisObj"></param> 91 /// <param name="methodInfo"></param> 92 /// <param name="param1"></param> 93 /// <param name="param2"></param> 94 /// <param name="param3"></param> 95 public void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3) 96 { 97 Check.Require(thisObj, "thisObj"); 98 Check.Require(methodInfo, "methodInfo"); 99 100 this.VerifyParameterCount(methodInfo, 3); 101 this.LoadThis(thisObj, methodInfo); 102 this.LoadParam(param1, 1, methodInfo); 103 this.LoadParam(param2, 2, methodInfo); 104 this.LoadParam(param3, 3, methodInfo); 105 this.Call(methodInfo); 106 } 107 108 /// <summary> 109 /// Call 110 /// </summary> 111 /// <param name="thisObj"></param> 112 /// <param name="methodInfo"></param> 113 /// <param name="param1"></param> 114 /// <param name="param2"></param> 115 /// <param name="param3"></param> 116 /// <param name="param4"></param> 117 public void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4) 118 { 119 Check.Require(thisObj, "thisObj"); 120 Check.Require(methodInfo, "methodInfo"); 121 122 this.VerifyParameterCount(methodInfo, 4); 123 this.LoadThis(thisObj, methodInfo); 124 //LoadParam:将参数变量转换成 方法中第N个参数的类型,加载到堆栈 125 this.LoadParam(param1, 1, methodInfo); 126 this.LoadParam(param2, 2, methodInfo); 127 this.LoadParam(param3, 3, methodInfo); 128 this.LoadParam(param4, 4, methodInfo); 129 this.Call(methodInfo); 130 } 131 132 /// <summary> 133 /// Call 134 /// </summary> 135 /// <param name="thisObj"></param> 136 /// <param name="methodInfo"></param> 137 /// <param name="param1"></param> 138 /// <param name="param2"></param> 139 /// <param name="param3"></param> 140 /// <param name="param4"></param> 141 /// <param name="param5"></param> 142 public void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5) 143 { 144 Check.Require(thisObj, "thisObj"); 145 Check.Require(methodInfo, "methodInfo"); 146 147 this.VerifyParameterCount(methodInfo, 5); 148 this.LoadThis(thisObj, methodInfo); 149 this.LoadParam(param1, 1, methodInfo); 150 this.LoadParam(param2, 2, methodInfo); 151 this.LoadParam(param3, 3, methodInfo); 152 this.LoadParam(param4, 4, methodInfo); 153 this.LoadParam(param5, 5, methodInfo); 154 this.Call(methodInfo); 155 } 156 157 /// <summary> 158 /// Call 159 /// </summary> 160 /// <param name="thisObj"></param> 161 /// <param name="methodInfo"></param> 162 /// <param name="param1"></param> 163 /// <param name="param2"></param> 164 /// <param name="param3"></param> 165 /// <param name="param4"></param> 166 /// <param name="param5"></param> 167 /// <param name="param6"></param> 168 public void Call(object thisObj, MethodInfo methodInfo, object param1, object param2, object param3, object param4, object param5, object param6) 169 { 170 Check.Require(thisObj, "thisObj"); 171 Check.Require(methodInfo, "methodInfo"); 172 173 this.VerifyParameterCount(methodInfo, 6); 174 this.LoadThis(thisObj, methodInfo); 175 this.LoadParam(param1, 1, methodInfo); 176 this.LoadParam(param2, 2, methodInfo); 177 this.LoadParam(param3, 3, methodInfo); 178 this.LoadParam(param4, 4, methodInfo); 179 this.LoadParam(param5, 5, methodInfo); 180 this.LoadParam(param6, 6, methodInfo); 181 this.Call(methodInfo); 182 } 183 184 185 /// <summary> 186 /// VerifyParameterCount 187 /// </summary> 188 /// <param name="methodInfo"></param> 189 /// <param name="expectedCount"></param> 190 public void VerifyParameterCount(MethodInfo methodInfo, int expectedCount) 191 { 192 Check.Require(methodInfo, "methodInfo"); 193 194 if (methodInfo.GetParameters().Length != expectedCount) 195 { 196 throw new Exception("ParameterCountMismatch"); 197 } 198 }