Beispiel #1
0
        private static void BuildMethodsInType(TypeDebugging type)
        {
            using (var ctor = type.GetMethodDebugging(
                       type.Builder.DefineConstructor(
                           MethodAttributes.Public | MethodAttributes.SpecialName |
                           MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                           CallingConventions.Standard, Type.EmptyTypes)))
            {
                ctor.Emit(OpCodes.Ldarg_0);
                var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes);
                ctor.Emit(OpCodes.Call, objectCtor);
                ctor.Emit(OpCodes.Ret);
            }

            using (var method = type.GetMethodDebugging(
                       type.Builder.DefineMethod("ReflectArgument",
                                                 MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public,
                                                 typeof(int), new Type[] { typeof(int) })))
            {
                method.Emit(OpCodes.Ldarg_0);
                method.Emit(OpCodes.Ret);
            }

            type.Builder.CreateType();
        }
        private static void BuildConstructor(TypeBuilder proxyBuilder, Type proxyType,
			 FieldBuilder wrappedType, FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments = new Type[] { proxyType, typeof(IInvocationHandler[]) };
            var constructor = proxyBuilder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                CallingConventions.Standard, arguments);

            using (var generator = debug.GetMethodDebugging(constructor))
            {
                //  Call the base constructor.
                generator.Emit(OpCodes.Ldarg_0);
                var objectCtor = proxyType.GetConstructor(Type.EmptyTypes);
                generator.Emit(OpCodes.Call, objectCtor);
                //  Store the target object.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Stfld, wrappedType);
                //  Store the handlers.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldarg_2);
                generator.Emit(OpCodes.Stfld, invokeHandlers);
                generator.Emit(OpCodes.Ret);
            }
        }
Beispiel #3
0
        private static void BuildConstructor(TypeBuilder proxyBuilder, Type proxyType,
                                             FieldBuilder wrappedType, FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments   = new Type[] { proxyType, typeof(IInvocationHandler[]) };
            var constructor = proxyBuilder.DefineConstructor(
                MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                CallingConventions.Standard, arguments);

            using (var generator = debug.GetMethodDebugging(constructor))
            {
                //  Call the base constructor.
                generator.Emit(OpCodes.Ldarg_0);
                var objectCtor = proxyType.GetConstructor(Type.EmptyTypes);
                generator.Emit(OpCodes.Call, objectCtor);
                //  Store the target object.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Stfld, wrappedType);
                //  Store the handlers.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldarg_2);
                generator.Emit(OpCodes.Stfld, invokeHandlers);
                generator.Emit(OpCodes.Ret);
            }
        }
        public static void CallGetMethodDebuggingWithMethodBuilderAfterDisposing()
        {
            TypeDebugging type = null;

            using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me"))
            {
                using (type = AssemblyCreationTests.CreateDebuggingType(assembly,
                                                                        assembly.Builder.GetDynamicModule("Me"), "Type")) { }

                Assert.Throws <ObjectDisposedException>(() => type.GetMethodDebugging(null as MethodBuilder));
            }
        }
        private static void BuildParameterlessConstructor(TypeBuilder proxyBuilder, Type proxyType,
			TypeDebugging debug)
        {
            var constructor = proxyBuilder.DefineConstructor(
                MethodAttributes.Private | MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                CallingConventions.Standard, Type.EmptyTypes);

            using (var generator = debug.GetMethodDebugging(constructor))
            {
                generator.Emit(OpCodes.Ldarg_0);
                var objectCtor = proxyType.GetConstructor(Type.EmptyTypes);
                generator.Emit(OpCodes.Call, objectCtor);
                generator.Emit(OpCodes.Ret);
            }
        }
Beispiel #6
0
        private static void BuildParameterlessConstructor(TypeBuilder proxyBuilder, Type proxyType,
                                                          TypeDebugging debug)
        {
            var constructor = proxyBuilder.DefineConstructor(
                MethodAttributes.Private | MethodAttributes.SpecialName |
                MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                CallingConventions.Standard, Type.EmptyTypes);

            using (var generator = debug.GetMethodDebugging(constructor))
            {
                generator.Emit(OpCodes.Ldarg_0);
                var objectCtor = proxyType.GetConstructor(Type.EmptyTypes);
                generator.Emit(OpCodes.Call, objectCtor);
                generator.Emit(OpCodes.Ret);
            }
        }
        private static void BuildIProxyTargetPropertyMethod(
			TypeBuilder proxyBuilder, Type targetType, Type iProxyType,
			FieldBuilder wrappedObject, TypeDebugging debug)
        {
            var attributes = MethodAttributes.HideBySig |
                 MethodAttributes.Virtual | MethodAttributes.Private;
            var method = proxyBuilder.DefineMethod(GetTargetMethod,
                 attributes, targetType, Type.EmptyTypes);
            proxyBuilder.DefineMethodOverride(method,
                iProxyType.GetProperty(TargetProperty).GetGetMethod());

            using (var generator = debug.GetMethodDebugging(method))
            {
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, wrappedObject);
                generator.Emit(OpCodes.Ret);
            }
        }
Beispiel #8
0
        private static void BuildIProxyTargetPropertyMethod(
            TypeBuilder proxyBuilder, Type targetType, Type iProxyType,
            FieldBuilder wrappedObject, TypeDebugging debug)
        {
            var attributes = MethodAttributes.HideBySig |
                             MethodAttributes.Virtual | MethodAttributes.Private;
            var method = proxyBuilder.DefineMethod(GetTargetMethod,
                                                   attributes, targetType, Type.EmptyTypes);

            proxyBuilder.DefineMethodOverride(method,
                                              iProxyType.GetProperty(TargetProperty).GetGetMethod());

            using (var generator = debug.GetMethodDebugging(method))
            {
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, wrappedObject);
                generator.Emit(OpCodes.Ret);
            }
        }
        private static void BuildMethodsInType(TypeDebugging type)
        {
            using (var ctor = type.GetMethodDebugging(
                type.Builder.DefineConstructor(
                    MethodAttributes.Public | MethodAttributes.SpecialName |
                    MethodAttributes.RTSpecialName | MethodAttributes.HideBySig,
                    CallingConventions.Standard, Type.EmptyTypes)))
            {
                ctor.Emit(OpCodes.Ldarg_0);
                var objectCtor = typeof(object).GetConstructor(Type.EmptyTypes);
                ctor.Emit(OpCodes.Call, objectCtor);
                ctor.Emit(OpCodes.Ret);
            }

            using (var method = type.GetMethodDebugging(
                type.Builder.DefineMethod("ReflectArgument",
                MethodAttributes.HideBySig | MethodAttributes.Static | MethodAttributes.Public,
                typeof(int), new Type[] { typeof(int) })))
            {
                method.Emit(OpCodes.Ldarg_0);
                method.Emit(OpCodes.Ret);
            }

            type.Builder.CreateType();
        }
        private static MethodBuilder BuildOnAfterMethodInvocation(TypeBuilder proxyBuilder,
			FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments = new Type[] { typeof(MethodBase), typeof(object[]),
                Type.GetType("System.Object&"), typeof(Exception) };

            var method = proxyBuilder.DefineMethod(OnAfterMethodInvocationMethod,
                MethodAttributes.Private | MethodAttributes.HideBySig,
                CallingConventions.HasThis,
                typeof(void), arguments);

            method.DefineParameter(1, ParameterAttributes.In, "currentMethod");
            method.DefineParameter(2, ParameterAttributes.In, "arguments");
            method.DefineParameter(3, ParameterAttributes.In | ParameterAttributes.Out, "returnValue");
            method.DefineParameter(4, ParameterAttributes.In, "generatedException");

            using (var generator = debug.GetMethodDebugging(method))
            {
                var i = generator.DeclareLocal(typeof(Int32));
                var throwException = generator.DeclareLocal(typeof(bool));

                var doNextHandlerAfterEx = generator.DefineLabel();
                var incrementIAfterEx = generator.DefineLabel();

                //  Reset i = 0;
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Stloc, i);
                generator.MarkLabel(doNextHandlerAfterEx);
                //  Load the next handler.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldelem_Ref);
                //  Load the handler's arguments.
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Ldarg_2);
                generator.Emit(OpCodes.Ldarg_3);
                generator.Emit(OpCodes.Ldarg, 4);
                //  AfterInvocationHandler
                generator.Emit(OpCodes.Callvirt,
                    typeof(IInvocationHandler).GetMethod(AfterInvocation));
                //  If the return value == true, rethrow generatedException.
                generator.Emit(OpCodes.Stloc, throwException);
                generator.Emit(OpCodes.Ldloc, throwException);
                generator.Emit(OpCodes.Brfalse, incrementIAfterEx);
                generator.Emit(OpCodes.Ldarg, 4);
                generator.Emit(OpCodes.Throw);
                //  Increment i.
                generator.MarkLabel(incrementIAfterEx);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldc_I4_1);
                generator.Emit(OpCodes.Add);
                generator.Emit(OpCodes.Stloc, i);
                //  See if i < invokeHandlers.Length.
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldlen);
                generator.Emit(OpCodes.Conv_I4);
                generator.Emit(OpCodes.Blt, doNextHandlerAfterEx);
                //  Exit loop and return
                generator.Emit(OpCodes.Ret);
            }

            return method;
        }
        private static void BuildTargetMethods(TypeBuilder proxyBuilder, MethodBuilder onBeforeMethodInvocation,
			MethodBuilder onAfterMethodInvocation, Type targetType,
			FieldBuilder wrappedObject, Dictionary<MethodInfo, MethodMappings> targets, TypeDebugging debug)
        {
            var methodAttribs = MethodAttributes.HideBySig |
                MethodAttributes.Virtual | MethodAttributes.Private;

            foreach (var target in targets)
            {
                var targetMethod = target.Key;
                var arguments = new Type[targetMethod.GetParameters().Length];

                for (int i = 0; i < targetMethod.GetParameters().Length; i++)
                {
                    arguments[i] = targetMethod.GetParameters()[i].ParameterType;
                }

                var method = proxyBuilder.DefineMethod(
                    targetMethod.Name + Proxy.ProxyExtension, methodAttribs, targetMethod.ReturnType, arguments);

                ProxyMethodBuilder.HandleGenericMethodArguments(targetMethod, method);

                //  Determine if this method should override
                //  the mapped method (OverridesInterfaceMethods == false)
                //  or a number of itf. methods (OverridesInterfaceMethods == true)
                var mappings = target.Value;

                if (!mappings.OverridesInterfaceMethods)
                {
                    proxyBuilder.DefineMethodOverride(method, targetMethod);
                }
                else
                {
                    for (int itfs = 0; itfs < mappings.MappedMethods.Count; itfs++)
                    {
                        proxyBuilder.DefineMethodOverride(method, mappings.MappedMethods[itfs]);
                    }
                }

                using (var generator = debug.GetMethodDebugging(method))
                {
                    var argumentValues = generator.DeclareLocal(typeof(object[]));
                    var callMethod = generator.DeclareLocal(typeof(bool));
                    generator.DeclareLocal(typeof(Type));
                    var generatedException = generator.DeclareLocal(typeof(Exception));
                    LocalBuilder returnValue = null;
                    var wrappedReturnValue = generator.DeclareLocal(typeof(object));
                    var baseMethod = generator.DeclareLocal(typeof(MethodBase));

                    var endCall = generator.DefineLabel();

                    //  Check for a return value.
                    if (targetMethod.ReturnType != typeof(void))
                    {
                        returnValue = generator.DeclareLocal(targetMethod.ReturnType);
                    }

                    generator.Emit(OpCodes.Ldnull);
                    generator.Emit(OpCodes.Stloc, generatedException);

                    generator.Emit(OpCodes.Ldc_I4, targetMethod.GetParameters().Length);
                    generator.Emit(OpCodes.Newarr, typeof(object));
                    generator.Emit(OpCodes.Stloc, argumentValues);

                    // Get the target method.
                    generator.Emit(OpCodes.Ldtoken, targetMethod);

                    if (targetType.IsGenericType)
                    {
                        generator.Emit(OpCodes.Ldtoken, targetType);
                        generator.Emit(OpCodes.Call,
                            typeof(MethodBase).GetMethod(GetMethodFromHandleMethod,
                            new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
                    }
                    else
                    {
                        generator.Emit(OpCodes.Call,
                            typeof(MethodBase).GetMethod(GetMethodFromHandleMethod,
                            new Type[] { typeof(RuntimeMethodHandle) }));
                    }

                    generator.Emit(OpCodes.Stloc, baseMethod);

                    // call OnBeforeMethodInvocation.
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, true);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    generator.Emit(OpCodes.Call, onBeforeMethodInvocation);
                    generator.Emit(OpCodes.Stloc, callMethod);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, true);

                    // If the call should be cancelled, break to the end.
                    generator.Emit(OpCodes.Ldloc, callMethod);
                    generator.Emit(OpCodes.Brfalse, endCall);

                    // Call the real method.
                    generator.BeginExceptionBlock();
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldfld, wrappedObject);

                    for (var argLoad = 0; argLoad < targetMethod.GetParameters().Length; argLoad++)
                    {
                        generator.Emit(OpCodes.Ldarg, argLoad + 1);
                    }

                    generator.Emit(OpCodes.Callvirt, targetMethod);

                    if (targetMethod.ReturnType != typeof(void))
                    {
                        generator.Emit(OpCodes.Stloc, returnValue);
                    }

                    // call OnAfterInvocation
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, false);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    ProxyMethodBuilder.WrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    generator.Emit(OpCodes.Ldloc, generatedException);
                    generator.Emit(OpCodes.Call, onAfterMethodInvocation);
                    ProxyMethodBuilder.UnwrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, false);

                    generator.BeginCatchBlock(typeof(Exception));
                    // call OnAfterInvocationWithException
                    generator.Emit(OpCodes.Stloc, generatedException);
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, false);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    ProxyMethodBuilder.WrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    generator.Emit(OpCodes.Ldloc, generatedException);
                    generator.Emit(OpCodes.Call, onAfterMethodInvocation);
                    ProxyMethodBuilder.UnwrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, false);
                    generator.EndExceptionBlock();
                    generator.MarkLabel(endCall);

                    //  Finally...return.
                    if (targetMethod.ReturnType != typeof(void))
                    {
                        generator.Emit(OpCodes.Ldloc, returnValue);
                    }

                    generator.Emit(OpCodes.Ret);
                }
            }
        }
        private static MethodBuilder BuildOnBeforeMethodInvocation(
			TypeBuilder proxyBuilder, FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments = new Type[] { typeof(MethodBase), typeof(object[]) };

            var method = proxyBuilder.DefineMethod(OnBeforeMethodInvocationMethod,
                MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis,
                typeof(bool), arguments);

            method.DefineParameter(1, ParameterAttributes.In, "currentMethod");
            method.DefineParameter(2, ParameterAttributes.In, "arguments");

            using (var generator = debug.GetMethodDebugging(method))
            {
                var callMethod = generator.DeclareLocal(typeof(bool));
                var i = generator.DeclareLocal(typeof(Int32));
                var doNextHandler = generator.DefineLabel();
                var incrementI = generator.DefineLabel();
                var finish = generator.DefineLabel();

                // Initial local setup.
                //  i = 0
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Stloc, i);

                // BeforeInvocationHandler Iteration
                //  Call BeforeInvocationHandler on each IL ref
                //  in invokeHandlers.
                generator.MarkLabel(doNextHandler);
                //  Load the next handler.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldelem_Ref);
                //  Load the handler's arguments.
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Ldarg_2);
                //  BeforeInvocationHandler.
                generator.Emit(OpCodes.Callvirt,
                    typeof(IInvocationHandler).GetMethod(BeforeInvocation));
                generator.Emit(OpCodes.Stloc, callMethod);
                generator.Emit(OpCodes.Ldloc, callMethod);
                //  If the return value == false, stop loop.
                generator.Emit(OpCodes.Brtrue, incrementI);
                generator.Emit(OpCodes.Br, finish);
                //  Increment i.
                generator.MarkLabel(incrementI);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldc_I4_1);
                generator.Emit(OpCodes.Add);
                generator.Emit(OpCodes.Stloc, i);
                //  See if i < invokeHandlers.Length.
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldlen);
                generator.Emit(OpCodes.Conv_I4);
                generator.Emit(OpCodes.Blt, doNextHandler);
                //  Exit loop.
                generator.MarkLabel(finish);
                //  Put callMethod on the stack and return.
                generator.Emit(OpCodes.Ldloc, callMethod);
                generator.Emit(OpCodes.Ret);
            }

            return method;
        }
Beispiel #13
0
        private static MethodBuilder BuildOnBeforeMethodInvocation(
            TypeBuilder proxyBuilder, FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments = new Type[] { typeof(MethodBase), typeof(object[]) };

            var method = proxyBuilder.DefineMethod(OnBeforeMethodInvocationMethod,
                                                   MethodAttributes.Private | MethodAttributes.HideBySig, CallingConventions.HasThis,
                                                   typeof(bool), arguments);

            method.DefineParameter(1, ParameterAttributes.In, "currentMethod");
            method.DefineParameter(2, ParameterAttributes.In, "arguments");

            using (var generator = debug.GetMethodDebugging(method))
            {
                var callMethod    = generator.DeclareLocal(typeof(bool));
                var i             = generator.DeclareLocal(typeof(Int32));
                var doNextHandler = generator.DefineLabel();
                var incrementI    = generator.DefineLabel();
                var finish        = generator.DefineLabel();

                // Initial local setup.
                //  i = 0
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Stloc, i);

                // BeforeInvocationHandler Iteration
                //  Call BeforeInvocationHandler on each IL ref
                //  in invokeHandlers.
                generator.MarkLabel(doNextHandler);
                //  Load the next handler.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldelem_Ref);
                //  Load the handler's arguments.
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Ldarg_2);
                //  BeforeInvocationHandler.
                generator.Emit(OpCodes.Callvirt,
                               typeof(IInvocationHandler).GetMethod(BeforeInvocation));
                generator.Emit(OpCodes.Stloc, callMethod);
                generator.Emit(OpCodes.Ldloc, callMethod);
                //  If the return value == false, stop loop.
                generator.Emit(OpCodes.Brtrue, incrementI);
                generator.Emit(OpCodes.Br, finish);
                //  Increment i.
                generator.MarkLabel(incrementI);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldc_I4_1);
                generator.Emit(OpCodes.Add);
                generator.Emit(OpCodes.Stloc, i);
                //  See if i < invokeHandlers.Length.
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldlen);
                generator.Emit(OpCodes.Conv_I4);
                generator.Emit(OpCodes.Blt, doNextHandler);
                //  Exit loop.
                generator.MarkLabel(finish);
                //  Put callMethod on the stack and return.
                generator.Emit(OpCodes.Ldloc, callMethod);
                generator.Emit(OpCodes.Ret);
            }

            return(method);
        }
Beispiel #14
0
        private static void BuildTargetMethods(TypeBuilder proxyBuilder, MethodBuilder onBeforeMethodInvocation,
                                               MethodBuilder onAfterMethodInvocation, Type targetType,
                                               FieldBuilder wrappedObject, Dictionary <MethodInfo, MethodMappings> targets, TypeDebugging debug)
        {
            var methodAttribs = MethodAttributes.HideBySig |
                                MethodAttributes.Virtual | MethodAttributes.Private;

            foreach (var target in targets)
            {
                var targetMethod = target.Key;
                var arguments    = new Type[targetMethod.GetParameters().Length];

                for (int i = 0; i < targetMethod.GetParameters().Length; i++)
                {
                    arguments[i] = targetMethod.GetParameters()[i].ParameterType;
                }

                var method = proxyBuilder.DefineMethod(
                    targetMethod.Name + Proxy.ProxyExtension, methodAttribs, targetMethod.ReturnType, arguments);

                ProxyMethodBuilder.HandleGenericMethodArguments(targetMethod, method);

                //  Determine if this method should override
                //  the mapped method (OverridesInterfaceMethods == false)
                //  or a number of itf. methods (OverridesInterfaceMethods == true)
                var mappings = target.Value;

                if (!mappings.OverridesInterfaceMethods)
                {
                    proxyBuilder.DefineMethodOverride(method, targetMethod);
                }
                else
                {
                    for (int itfs = 0; itfs < mappings.MappedMethods.Count; itfs++)
                    {
                        proxyBuilder.DefineMethodOverride(method, mappings.MappedMethods[itfs]);
                    }
                }

                using (var generator = debug.GetMethodDebugging(method))
                {
                    var argumentValues = generator.DeclareLocal(typeof(object[]));
                    var callMethod     = generator.DeclareLocal(typeof(bool));
                    generator.DeclareLocal(typeof(Type));
                    var          generatedException = generator.DeclareLocal(typeof(Exception));
                    LocalBuilder returnValue        = null;
                    var          wrappedReturnValue = generator.DeclareLocal(typeof(object));
                    var          baseMethod         = generator.DeclareLocal(typeof(MethodBase));

                    var endCall = generator.DefineLabel();

                    //  Check for a return value.
                    if (targetMethod.ReturnType != typeof(void))
                    {
                        returnValue = generator.DeclareLocal(targetMethod.ReturnType);
                    }

                    generator.Emit(OpCodes.Ldnull);
                    generator.Emit(OpCodes.Stloc, generatedException);

                    generator.Emit(OpCodes.Ldc_I4, targetMethod.GetParameters().Length);
                    generator.Emit(OpCodes.Newarr, typeof(object));
                    generator.Emit(OpCodes.Stloc, argumentValues);

                    // Get the target method.
                    generator.Emit(OpCodes.Ldtoken, targetMethod);

                    if (targetType.IsGenericType)
                    {
                        generator.Emit(OpCodes.Ldtoken, targetType);
                        generator.Emit(OpCodes.Call,
                                       typeof(MethodBase).GetMethod(GetMethodFromHandleMethod,
                                                                    new Type[] { typeof(RuntimeMethodHandle), typeof(RuntimeTypeHandle) }));
                    }
                    else
                    {
                        generator.Emit(OpCodes.Call,
                                       typeof(MethodBase).GetMethod(GetMethodFromHandleMethod,
                                                                    new Type[] { typeof(RuntimeMethodHandle) }));
                    }

                    generator.Emit(OpCodes.Stloc, baseMethod);

                    // call OnBeforeMethodInvocation.
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, true);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    generator.Emit(OpCodes.Call, onBeforeMethodInvocation);
                    generator.Emit(OpCodes.Stloc, callMethod);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, true);

                    // If the call should be cancelled, break to the end.
                    generator.Emit(OpCodes.Ldloc, callMethod);
                    generator.Emit(OpCodes.Brfalse, endCall);

                    // Call the real method.
                    generator.BeginExceptionBlock();
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldfld, wrappedObject);

                    for (var argLoad = 0; argLoad < targetMethod.GetParameters().Length; argLoad++)
                    {
                        generator.Emit(OpCodes.Ldarg, argLoad + 1);
                    }

                    generator.Emit(OpCodes.Callvirt, targetMethod);

                    if (targetMethod.ReturnType != typeof(void))
                    {
                        generator.Emit(OpCodes.Stloc, returnValue);
                    }

                    // call OnAfterInvocation
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, false);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    ProxyMethodBuilder.WrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    generator.Emit(OpCodes.Ldloc, generatedException);
                    generator.Emit(OpCodes.Call, onAfterMethodInvocation);
                    ProxyMethodBuilder.UnwrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, false);

                    generator.BeginCatchBlock(typeof(Exception));
                    // call OnAfterInvocationWithException
                    generator.Emit(OpCodes.Stloc, generatedException);
                    ProxyMethodBuilder.WindArguments(targetMethod, generator, argumentValues, false);
                    generator.Emit(OpCodes.Ldarg_0);
                    generator.Emit(OpCodes.Ldloc, baseMethod);
                    generator.Emit(OpCodes.Ldloc, argumentValues);
                    ProxyMethodBuilder.WrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    generator.Emit(OpCodes.Ldloc, generatedException);
                    generator.Emit(OpCodes.Call, onAfterMethodInvocation);
                    ProxyMethodBuilder.UnwrapReturnValue(targetMethod, generator, returnValue, wrappedReturnValue);
                    ProxyMethodBuilder.UnwindArguments(targetMethod, generator, argumentValues, false);
                    generator.EndExceptionBlock();
                    generator.MarkLabel(endCall);

                    //  Finally...return.
                    if (targetMethod.ReturnType != typeof(void))
                    {
                        generator.Emit(OpCodes.Ldloc, returnValue);
                    }

                    generator.Emit(OpCodes.Ret);
                }
            }
        }
Beispiel #15
0
        private static MethodBuilder BuildOnAfterMethodInvocation(TypeBuilder proxyBuilder,
                                                                  FieldBuilder invokeHandlers, TypeDebugging debug)
        {
            var arguments = new Type[] { typeof(MethodBase), typeof(object[]),
                                         Type.GetType("System.Object&"), typeof(Exception) };

            var method = proxyBuilder.DefineMethod(OnAfterMethodInvocationMethod,
                                                   MethodAttributes.Private | MethodAttributes.HideBySig,
                                                   CallingConventions.HasThis,
                                                   typeof(void), arguments);

            method.DefineParameter(1, ParameterAttributes.In, "currentMethod");
            method.DefineParameter(2, ParameterAttributes.In, "arguments");
            method.DefineParameter(3, ParameterAttributes.In | ParameterAttributes.Out, "returnValue");
            method.DefineParameter(4, ParameterAttributes.In, "generatedException");

            using (var generator = debug.GetMethodDebugging(method))
            {
                var i = generator.DeclareLocal(typeof(Int32));
                var throwException = generator.DeclareLocal(typeof(bool));

                var doNextHandlerAfterEx = generator.DefineLabel();
                var incrementIAfterEx    = generator.DefineLabel();

                //  Reset i = 0;
                generator.Emit(OpCodes.Ldc_I4_0);
                generator.Emit(OpCodes.Stloc, i);
                generator.MarkLabel(doNextHandlerAfterEx);
                //  Load the next handler.
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldelem_Ref);
                //  Load the handler's arguments.
                generator.Emit(OpCodes.Ldarg_1);
                generator.Emit(OpCodes.Ldarg_2);
                generator.Emit(OpCodes.Ldarg_3);
                generator.Emit(OpCodes.Ldarg, 4);
                //  AfterInvocationHandler
                generator.Emit(OpCodes.Callvirt,
                               typeof(IInvocationHandler).GetMethod(AfterInvocation));
                //  If the return value == true, rethrow generatedException.
                generator.Emit(OpCodes.Stloc, throwException);
                generator.Emit(OpCodes.Ldloc, throwException);
                generator.Emit(OpCodes.Brfalse, incrementIAfterEx);
                generator.Emit(OpCodes.Ldarg, 4);
                generator.Emit(OpCodes.Throw);
                //  Increment i.
                generator.MarkLabel(incrementIAfterEx);
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldc_I4_1);
                generator.Emit(OpCodes.Add);
                generator.Emit(OpCodes.Stloc, i);
                //  See if i < invokeHandlers.Length.
                generator.Emit(OpCodes.Ldloc, i);
                generator.Emit(OpCodes.Ldarg_0);
                generator.Emit(OpCodes.Ldfld, invokeHandlers);
                generator.Emit(OpCodes.Ldlen);
                generator.Emit(OpCodes.Conv_I4);
                generator.Emit(OpCodes.Blt, doNextHandlerAfterEx);
                //  Exit loop and return
                generator.Emit(OpCodes.Ret);
            }

            return(method);
        }