In the comments: here's how to do it from CIL, which can be generated with C #.
I was hoping to use DynamicMethod , but I can't get this to work without creating a custom delegate type at runtime, so I needed to use AssemblyBuilder instead.
using System; using System.Reflection; using System.Reflection.Emit; public delegate void CallBadFunction(Delegate d, Callback c); public delegate void Callback(ref int i); static class Program { static int i; static object BadMethod() { return i; } static MethodInfo GetBadMethod() { return typeof(Program).GetMethod("BadMethod", BindingFlags.Static | BindingFlags.NonPublic); } static void Main() { var badMethod = GetBadMethod(); var assembly = AssemblyBuilder.DefineDynamicAssembly(new AssemblyName("-"), AssemblyBuilderAccess.Run); var module = assembly.DefineDynamicModule("-"); var badDelegate = module.DefineType("BadDelegateType", TypeAttributes.Public | TypeAttributes.Class | TypeAttributes.Sealed, typeof(MulticastDelegate)); var badDelegateCtor = badDelegate.DefineConstructor(MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard, new Type[] { typeof(object), typeof(IntPtr) }); badDelegateCtor.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); var badDelegateInvoke = badDelegate.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.NewSlot | MethodAttributes.HideBySig, typeof(int).MakeByRefType(), Type.EmptyTypes); badDelegateInvoke.SetImplementationFlags(MethodImplAttributes.Runtime | MethodImplAttributes.Managed); var badDelegateType = badDelegate.CreateType(); var method = module.DefineGlobalMethod("-", MethodAttributes.Public | MethodAttributes.Static, typeof(void), new[] { typeof(Delegate), typeof(Callback) }); var il = method.GetILGenerator(); il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, badDelegate); il.Emit(OpCodes.Callvirt, badDelegateInvoke); il.Emit(OpCodes.Callvirt, typeof(Callback).GetMethod("Invoke")); il.Emit(OpCodes.Ret); module.CreateGlobalFunctions(); var callBadFunction = (CallBadFunction)Delegate.CreateDelegate(typeof(CallBadFunction), module.GetMethod("-")); callBadFunction(badMethod.CreateDelegate(badDelegateType), (ref int i) => { i++; }); } }
After compiling this program, use ILDASM to disassemble it and replace BadMethod with
.method private hidebysig static int32& BadMethod() cil managed { ldsflda int32 Program::i ret }
This turns it into a function that returns int32& , which is followed by the following code. The only place C # allows int32& type is in the function parameters ( ref int ), so to make the result useful, I used a callback function that gets the BadMethod return BadMethod .
source share