/// <summary> /// Defines the method parameters based on the specified method. /// </summary> /// <param name="methodBuilder">The method builder.</param> /// <param name="methodInfo">The method information.</param> /// <param name="genericTypes">The generic types.</param> public static void DefineParameters(this MethodBuilder methodBuilder, MethodInfo methodInfo, Type[] genericTypes) { if (methodBuilder == null) throw new ArgumentNullException("methodBuilder"); if (methodInfo == null) throw new ArgumentNullException("methodInfo"); // Set parameters and return type. var parameterTypes = methodInfo.MapGenericParameterTypes(genericTypes); var returnType = methodInfo.MapGenericReturnType(genericTypes); methodBuilder.SetReturnType(returnType); methodBuilder.SetParameters(parameterTypes); // Define method parameters. No need to define parameter 0 for return type. var parameterInfos = methodInfo.GetParameters(); foreach (var parameterInfo in parameterInfos) { methodBuilder.DefineParameter(parameterInfo.Position + 1, parameterInfo.Attributes, parameterInfo.Name); } }
/// <summary> /// Builds an intercepted method based on the specified method. /// </summary> /// <param name="methodInfo">The method information.</param> /// <param name="isExplicit">A value indicating whether the specified method should be implemented explicitly.</param> /// <returns>The intercepted method builder.</returns> private MethodBuilder BuildInterceptedMethod(MethodInfo methodInfo, bool isExplicit) { var isOverride = IsOverrideMember(methodInfo); if (isOverride && !methodInfo.CanOverride()) throw new InvalidOperationException(String.Format(Resources.MethodNotOverridable, methodInfo.Name)); // Define method. var methodBuilder = _typeBuilder.DefineMethod(methodInfo, isExplicit, isOverride); // Define generic parameters. var genericParameterTypes = methodBuilder.DefineGenericParameters(methodInfo); // Define parameters. methodBuilder.DefineParameters(methodInfo, genericParameterTypes); // Only define method override if method is implemented explicitly and is an override. if (isExplicit && isOverride) _typeBuilder.DefineMethodOverride(methodBuilder, methodInfo); // Implement method. var ilGenerator = methodBuilder.GetILGenerator(); // Load arguments. var parameterTypes = methodInfo.MapGenericParameterTypes(genericParameterTypes); var parametersLocalBuilder = ilGenerator.NewArray(typeof (object), parameterTypes.Length); LoadArguments(ilGenerator, parameterTypes, parametersLocalBuilder); // Load invocation handler. ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(OpCodes.Ldfld, _invocationHandlerFieldInfo); // Load proxy object. ilGenerator.Emit(OpCodes.Ldarg_0); // Get method information constructor. var methodInfoConstructorInfo = GetMethodInfoConstructor(methodInfo, genericParameterTypes); // Create and load method information. ilGenerator.Emit(OpCodes.Ldarg_0); ilGenerator.Emit(isOverride ? OpCodes.Ldc_I4_1 : OpCodes.Ldc_I4_0); ilGenerator.Emit(OpCodes.Newobj, methodInfoConstructorInfo); // Load parameters. ilGenerator.Emit(OpCodes.Ldloc, parametersLocalBuilder); // Call invocation handler method. ilGenerator.EmitCall(InvocationHandlerInvokeMethodInfo); // Restore by reference arguments. RestoreByReferenceArguments(ilGenerator, parameterTypes, parametersLocalBuilder); // Handle return value. var returnType = methodInfo.MapGenericReturnType(genericParameterTypes); if (returnType.IsVoid()) ilGenerator.Emit(OpCodes.Pop); else ilGenerator.EmitUnbox(returnType); ilGenerator.Emit(OpCodes.Ret); return methodBuilder; }
/// <summary> /// Builds the invoke method. /// </summary> /// <param name="typeBuilder">The type builder.</param> /// <param name="methodInfo">The method information.</param> /// <param name="genericParameterTypes">The generic parameter types.</param> /// <param name="isVirtual">A value indicating whether the method should be called virtually.</param> private static void BuildInvokeMethod(TypeBuilder typeBuilder, MethodInfo methodInfo, Type[] genericParameterTypes, bool isVirtual) { var invokeMethodInfo = isVirtual ? MethodInfoBaseInvokeVirtualMethodInfo : MethodInfoBaseInvokeBaseMethodInfo; // Define method. var methodBuilder = typeBuilder.DefineMethod(invokeMethodInfo, false, true); methodBuilder.DefineParameters(invokeMethodInfo); // Implement method. var ilGenerator = methodBuilder.GetILGenerator(); // Load target object. ilGenerator.Emit(OpCodes.Ldarg_1); // Load parameter values. var parameterTypes = methodInfo.MapGenericParameterTypes(genericParameterTypes); var parameterValueLocalBuilders = new LocalBuilder[parameterTypes.Length]; LoadParameterValues(ilGenerator, 2, parameterTypes, parameterValueLocalBuilders); // Call target method. var targetMethodInfo = methodInfo.MapGenericMethod(genericParameterTypes); ilGenerator.Emit(isVirtual ? OpCodes.Callvirt : OpCodes.Call, targetMethodInfo); // Restore by reference parameter values. RestoreByReferenceParameterValues(ilGenerator, 2, parameterTypes, parameterValueLocalBuilders); // Handle return value. var returnType = methodInfo.MapGenericReturnType(genericParameterTypes); if (returnType.IsVoid()) ilGenerator.Emit(OpCodes.Ldnull); else ilGenerator.EmitBox(returnType); ilGenerator.Emit(OpCodes.Ret); }