/// <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);
            }
        }
Esempio n. 2
0
        /// <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;
        }
Esempio n. 3
0
        /// <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);
        }