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); } }
internal static TypeBuilder Build(ModuleBuilder proxyModule, Type proxyType, AssemblyDebugging debugAssembly) { TypeBuilder proxyTypeBuilder = null; string proxyName = proxyType.Namespace + "." + proxyType.Name + Proxy.ProxyExtension; var iProxyType = typeof(IProxy <>).MakeGenericType(proxyType); proxyTypeBuilder = proxyModule.DefineType(proxyName, TypeAttributes.Class | TypeAttributes.Sealed | TypeAttributes.Public, proxyType, new Type[] { iProxyType }); using (TypeDebugging debugType = debugAssembly.GetTypeDebugging(proxyTypeBuilder)) { var fields = ProxyFieldBuilder.Build( proxyTypeBuilder, proxyType); ProxyConstructorBuilder.Build(proxyTypeBuilder, proxyType, fields[ProxyFieldBuilder.WrappedObjectField], fields[ProxyFieldBuilder.InvokeHandlerField], debugType); ProxyMethodBuilder.Build(proxyTypeBuilder, proxyType, iProxyType, fields[ProxyFieldBuilder.WrappedObjectField], fields[ProxyFieldBuilder.InvokeHandlerField], debugType); } return(proxyTypeBuilder); }
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(); }
internal static void Build(TypeBuilder proxyBuilder, Type proxyType, FieldBuilder wrappedObject, FieldBuilder invokeHandlers, TypeDebugging debug) { ProxyConstructorBuilder.BuildParameterlessConstructor( proxyBuilder, proxyType, debug); ProxyConstructorBuilder.BuildConstructor( proxyBuilder, proxyType, wrappedObject, invokeHandlers, debug); }
public static void CallDisposeAfterDisposing() { TypeDebugging type = null; using (var assembly = AssemblyCreationTests.CreateDebuggingAssembly("Me")) { using (type = AssemblyCreationTests.CreateDebuggingType(assembly, assembly.Builder.GetDynamicModule("Me"), "Type")) { } type.Dispose(); } }
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)); } }
internal static void Build(TypeBuilder proxyBuilder, Type targetType, Type iProxyType, FieldBuilder wrappedObject, FieldBuilder invokeHandlers, TypeDebugging debug) { ProxyMethodBuilder.BuildIProxyTargetPropertyMethod( proxyBuilder, targetType, iProxyType, wrappedObject, debug); MethodBuilder onBeforeMethodInvocation = ProxyMethodBuilder.BuildOnBeforeMethodInvocation(proxyBuilder, invokeHandlers, debug); MethodBuilder onAfterMethodInvocation = ProxyMethodBuilder.BuildOnAfterMethodInvocation(proxyBuilder, invokeHandlers, debug); ProxyMethodBuilder.BuildTargetMethods(proxyBuilder, onBeforeMethodInvocation, onAfterMethodInvocation, targetType, wrappedObject, ProxyMethodBuilder.GetTargetMethods(targetType), debug); }
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 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); } }
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 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 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; }
internal static void Build(TypeBuilder proxyBuilder, Type proxyType, FieldBuilder wrappedObject, FieldBuilder invokeHandlers, TypeDebugging debug) { ProxyConstructorBuilder.BuildParameterlessConstructor( proxyBuilder, proxyType, debug); ProxyConstructorBuilder.BuildConstructor( proxyBuilder, proxyType, wrappedObject, invokeHandlers, debug); }
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 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; }
internal static void Build(TypeBuilder proxyBuilder, Type targetType, Type iProxyType, FieldBuilder wrappedObject, FieldBuilder invokeHandlers, TypeDebugging debug) { ProxyMethodBuilder.BuildIProxyTargetPropertyMethod( proxyBuilder, targetType, iProxyType, wrappedObject, debug); MethodBuilder onBeforeMethodInvocation = ProxyMethodBuilder.BuildOnBeforeMethodInvocation(proxyBuilder, invokeHandlers, debug); MethodBuilder onAfterMethodInvocation = ProxyMethodBuilder.BuildOnAfterMethodInvocation(proxyBuilder, invokeHandlers, debug); ProxyMethodBuilder.BuildTargetMethods(proxyBuilder, onBeforeMethodInvocation, onAfterMethodInvocation, targetType, wrappedObject, ProxyMethodBuilder.GetTargetMethods(targetType), debug); }
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); }
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); } }