private static OpCode GetStindInstruction(System.Type parameterType) { if (parameterType.IsByRef) { OpCode stindOpCode; if(OpCodesMap.TryGetStindOpCode(parameterType.GetElementType(), out stindOpCode)) { return stindOpCode; } } return OpCodes.Stind_Ref; }
private static void SaveRefArguments(ILGenerator IL, ParameterInfo[] parameters) { // Save the arguments returned from the handler method IL.Emit(OpCodes.Ldloc_1); IL.Emit(OpCodes.Call, getArguments); IL.Emit(OpCodes.Stloc_0); foreach (ParameterInfo param in parameters) { string typeName = param.ParameterType.Name; bool isRef = param.ParameterType.IsByRef && typeName.EndsWith("&"); if (!isRef) { continue; } // Load the destination address IL.Emit(OpCodes.Ldarg, param.Position + 1); // Load the argument value IL.Emit(OpCodes.Ldloc_0); IL.Emit(OpCodes.Ldc_I4, param.Position); IL.Emit(OpCodes.Ldelem_Ref); System.Type unboxedType = param.ParameterType.GetElementType(); IL.Emit(OpCodes.Unbox_Any, unboxedType); if (Nullable.GetUnderlyingType(unboxedType) != null) { IL.Emit(OpCodes.Stobj, unboxedType); } else if (OpCodesMap.TryGetStindOpCode(param.ParameterType.GetElementType(), out var stind)) { IL.Emit(stind); } else { IL.Emit(OpCodes.Stind_Ref); } } }
public void PushArguments(ParameterInfo[] methodParameters, ILGenerator IL, bool isStatic) { ParameterInfo[] parameters = methodParameters ?? Array.Empty <ParameterInfo>(); int parameterCount = parameters.Length; // object[] args = new object[size]; IL.Emit(OpCodes.Ldc_I4, parameterCount); IL.Emit(OpCodes.Newarr, typeof(object)); IL.Emit(OpCodes.Stloc_S, 0); if (parameterCount == 0) { IL.Emit(OpCodes.Ldloc_S, 0); return; } // Populate the object array with the list of arguments int index = 0; int argumentPosition = 1; foreach (ParameterInfo param in parameters) { System.Type parameterType = param.ParameterType.IsByRef ? param.ParameterType.GetElementType() : param.ParameterType; // args[N] = argumentN (pseudocode) IL.Emit(OpCodes.Ldloc_S, 0); IL.Emit(OpCodes.Ldc_I4, index); // Zero out the [out] parameters if (param.IsOut) { IL.Emit(OpCodes.Ldnull); IL.Emit(OpCodes.Stelem_Ref); argumentPosition++; index++; continue; } IL.Emit(OpCodes.Ldarg, argumentPosition); if (param.ParameterType.IsByRef) { var unboxedType = param.ParameterType.GetElementType(); if (Nullable.GetUnderlyingType(unboxedType) != null) { IL.Emit(OpCodes.Ldobj, unboxedType); } else if (OpCodesMap.TryGetLdindOpCode(unboxedType, out var ldind)) { IL.Emit(ldind); } else { IL.Emit(OpCodes.Ldind_Ref); } } if (parameterType.IsValueType || param.ParameterType.IsByRef || parameterType.IsGenericParameter) { IL.Emit(OpCodes.Box, parameterType); } IL.Emit(OpCodes.Stelem_Ref); index++; argumentPosition++; } IL.Emit(OpCodes.Ldloc_S, 0); }