Skip to content

Instantly share code, notes, and snippets.

@leppie
Created April 23, 2015 08:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save leppie/dc6d4d3bbb1c6fc476db to your computer and use it in GitHub Desktop.
Save leppie/dc6d4d3bbb1c6fc476db to your computer and use it in GitHub Desktop.
Delegate conversion via reflection with DynamicMethod issue
using System;
using System.Reflection.Emit;
class Program
{
delegate object FuncObjectObject(Object o);
static void Main(string[] args)
{
var dm = new DynamicMethod("", typeof(object), new [] { typeof(object) });
var ilgen = dm.GetILGenerator();
ilgen.Emit(OpCodes.Ldarg_0);
ilgen.Emit(OpCodes.Ret);
var dmd = (Func<object, object>)dm.CreateDelegate(typeof(Func<object, object>));
Console.WriteLine(dmd(1)); // works
// now do the same, but with reflection
var rd = (FuncObjectObject) Delegate.CreateDelegate(typeof(FuncObjectObject), dmd.Target, dmd.Method); // kaboom!
// wrap the delegate
var sdm = new FuncObjectObject(dmd);
Console.WriteLine(sdm(1)); // works
var srd = (FuncObjectObject)Delegate.CreateDelegate(typeof(FuncObjectObject), sdm.Target, sdm.Method); // works
Console.WriteLine(srd(1));
// lets try something else
var ad = (FuncObjectObject) Activator.CreateInstance(typeof(FuncObjectObject), dmd); // kaboom!
}
}
@mgravell
Copy link

The constructor for delegates actually takes two parameters; the C# compiler lies and splits out the target and method for you; the actual usage would be:

var ad = (FuncObjectObject)Activator.CreateInstance(typeof(FuncObjectObject),
     sdm.Target, sdm.Method.MethodHandle.GetFunctionPointer());

However: it doesn't work with dynamic methods.

@mgravell
Copy link

For the rest: ultimately, dynamic methods have restrictions and limitations (but also: have some nice extra features, like the ability to spoof accessibility to a type outside your direct control). Some things don't work on them. If you need it to behave as a full method, you might need to use TypeBuilder and MethodBuilder to create a (presumably) static method on a dummy Type via CreateType() etc. Much more work.

@leppie
Copy link
Author

leppie commented Apr 23, 2015

yay, found a workaround!

var ad = (FuncObjectObject)Activator.CreateInstance(typeof(FuncObjectObject), 
     dmd, dmd.GetType().GetMethod("Invoke").MethodHandle.GetFunctionPointer()); // works!
Console.WriteLine(ad(1)); // works!

Thanks @mgravell for hinting towards to right direction 😄

@mgravell
Copy link

heh; nice

@mgravell
Copy link

Simpler:

var ad = (FuncObjectObject)Delegate.CreateDelegate(typeof(FuncObjectObject), dmd, "Invoke");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment