private static void UnwrapReturnValue(MethodInfo targetMethod, MethodDebugging generator, LocalBuilder returnValue, LocalBuilder wrappedReturnValue) { if (targetMethod.ReturnType != typeof(void)) { if (targetMethod.ReturnType.IsGenericParameter || targetMethod.ReturnType.IsValueType) { generator.Emit(OpCodes.Ldloc, wrappedReturnValue); generator.Emit(OpCodes.Unbox_Any, targetMethod.ReturnType); generator.Emit(OpCodes.Stloc, returnValue); } else { generator.Emit(OpCodes.Ldloc, wrappedReturnValue); generator.Emit(OpCodes.Castclass, targetMethod.ReturnType); generator.Emit(OpCodes.Stloc, returnValue); } } }
private static void WrapReturnValue(MethodInfo targetMethod, MethodDebugging generator, LocalBuilder returnValue, LocalBuilder wrappedReturnValue) { if (targetMethod.ReturnType != typeof(void)) { if (targetMethod.ReturnType.IsGenericParameter || targetMethod.ReturnType.IsValueType) { generator.Emit(OpCodes.Ldloc, returnValue); generator.Emit(OpCodes.Box, targetMethod.ReturnType); generator.Emit(OpCodes.Stloc, wrappedReturnValue); generator.Emit(OpCodes.Ldloca, wrappedReturnValue); } else { generator.Emit(OpCodes.Ldloc, returnValue); generator.Emit(OpCodes.Castclass, typeof(object)); generator.Emit(OpCodes.Stloc, wrappedReturnValue); generator.Emit(OpCodes.Ldloca, wrappedReturnValue); } } else { generator.Emit(OpCodes.Ldnull); generator.Emit(OpCodes.Stloc, wrappedReturnValue); generator.Emit(OpCodes.Ldloca, wrappedReturnValue); } }
private static void WindArguments(MethodInfo targetMethod, MethodDebugging generator, LocalBuilder argumentValues, bool isBeforeCall) { // Set up the arg array if (targetMethod.GetParameters().Length > 0) { for (int argLoad = 0; argLoad < targetMethod.GetParameters().Length; argLoad++) { var parameter = targetMethod.GetParameters()[argLoad]; var parameterType = parameter.ParameterType; if (isBeforeCall || parameterType.IsByRef) { generator.Emit(OpCodes.Ldloc, argumentValues); generator.Emit(OpCodes.Ldc_I4, argLoad); generator.Emit(OpCodes.Ldarg, argLoad + 1); if (parameterType.IsGenericParameter || parameterType.FullName == null) { if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); generator.Emit(OpCodes.Ldobj, parameterType); generator.Emit(OpCodes.Box, parameterType); } else { generator.Emit(OpCodes.Box, parameterType); } } else if (parameterType.IsValueType || (parameterType.HasElementType && parameterType.GetElementType().IsValueType)) { if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); var indirectCode = ProxyMethodBuilder.GetIndCode(parameterType, true); if (indirectCode == OpCodes.Ldobj) { generator.Emit(indirectCode, parameterType); } else { generator.Emit(indirectCode); } } generator.Emit(OpCodes.Box, parameterType); } else { if (parameterType.IsByRef) { generator.Emit(OpCodes.Ldind_Ref); } } generator.Emit(OpCodes.Stelem_Ref); } } } }
private static void UnwindArguments(MethodInfo targetMethod, MethodDebugging generator, LocalBuilder argumentValues, bool isBeforeCall) { if (targetMethod.GetParameters().Length > 0) { for (var argLoad = 0; argLoad < targetMethod.GetParameters().Length; argLoad++) { var parameter = targetMethod.GetParameters()[argLoad]; var parameterType = parameter.ParameterType; if (isBeforeCall || parameterType.IsByRef) { if (parameterType.IsByRef) { generator.Emit(OpCodes.Ldarg, argLoad + 1); } generator.Emit(OpCodes.Ldloc, argumentValues); generator.Emit(OpCodes.Ldc_I4, argLoad); generator.Emit(OpCodes.Ldelem_Ref); // This code is odd. By-ref generic parameters are not reported as generic, // so that's why the FullName null check is done. // Also, the Unbox_Any won't work with by-ref generic arguments, // so the generic type has to be found within the generic arguments array // off of the target method. if (parameterType.IsGenericParameter || parameterType.FullName == null) { if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); generator.Emit(OpCodes.Unbox_Any, parameterType); generator.Emit(OpCodes.Stobj, parameterType); } else { generator.Emit(OpCodes.Unbox_Any, parameterType); generator.Emit(OpCodes.Starg, argLoad + 1); } } else { if (parameterType.IsValueType || (parameterType.HasElementType && parameterType.GetElementType().IsValueType)) { if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); generator.Emit(OpCodes.Unbox_Any, parameterType); var indirectCode = ProxyMethodBuilder.GetIndCode(parameterType, false); if (indirectCode == OpCodes.Stobj) { generator.Emit(indirectCode, parameterType); } else { generator.Emit(indirectCode); } } else { generator.Emit(OpCodes.Unbox_Any, parameterType); generator.Emit(OpCodes.Starg, argLoad + 1); } } else { if (parameterType.IsByRef) { parameterType = parameterType.GetElementType(); generator.Emit(OpCodes.Castclass, parameterType); generator.Emit(OpCodes.Stind_Ref); } else { generator.Emit(OpCodes.Castclass, parameterType); generator.Emit(OpCodes.Starg, argLoad + 1); } } } } } } }