Description
When writing a framework that dispatches to user methods it's quite common to reflect over all methods of a particular shape on an object and store a MethodInfo
for later use. The scan and store is typically a one time cost (done up front) but the invocation of these methods happen lots of times (one or many times per http request for example). Historically, to make invocation fast, you would generate a DynamicMethod
using reflection emit or generate a compiled expression tree to invoke the method instead of using methodInfo.Invoke
. ASP.NET does this all the time, so much so that we now have a shared component to do this (as some of the code can be a bit tricky).
With the advent of newer runtimes like project N and coreRT, it would be great if there was first class support for creating a thunk to method. This is what I think it could look like:
class Program
{
// First class delegate type in the CLR use to express the stub that calls into the
// underlying method
public delegate object Thunk(object target, object[] arguments);
static void Main(string[] args)
{
var methods = typeof(Controller).GetMethods();
var map = new Dictionary<string, Thunk>();
foreach (var methodInfo in methods)
{
map[methodInfo.Name] = methodInfo.CreateThunk();
}
// Invoke the method index (result is null)
var result = Invoke(map, typeof(Controller), "Index");
// Result is 3 (yes things get boxed)
result = Invoke(map, typeof(Controller), "Add", 1, 2);
}
private static object Invoke(Dictionary<string, Thunk> map, Type type, string method, params object[] arguments)
{
var target = Activator.CreateInstance(type);
return map[method](target, arguments);
}
}
public class Controller
{
public void Index()
{
}
public int Add(int a, int b)
{
return a + b;
}
}
Few notes:
- We could disable type checking in the stub, if the caller passes the wrong arguments they would get an invalid cast exception.
- The arguments and return values are always boxed (that's not a huge deal for our use cases at least).