Being able to dynamically call an arbitrary method on an object or the ability to get/set any arbitrary property by name at run time is very important when it comes to do some generic stuff. In .NET Framework 1.x the only way to do that was using reflection and that means to do it slow. For simple things or if we don’t have a lot of concurrent users we can live with it, but sometimes the performance is important and reflection isn’t an acceptable solution.
Fortunately, the .NET Framework 2.0 introduces a new class that let us to quickly call an arbitrary method without the overhead of a reflection call. How? Well, the idea is to generate the same MSIL as the compiler generates when calling a function but on the fly, and then we obtain a delegate that when called will execute the MSIL we have just created. This is really useful in a lot of scenarios!
I read something about this in Marc’s blog (http://musingmarc.blogspot.com/) but I didn’t have time to look at it in more detail in that moment. Today I read an article at codeproject that talked about this (http://www.codeproject.com/useritems/FastMethodInvoker.asp) so I finally forced myself to spend some time playing with dynamic MSIL code generation and I’m quite impressed with the possibilities.
If you want to play with this you should download an excellent debugger visualizer that will let you show the MSIL generated by a DynamicMethod:
http://blogs.msdn.com/haibo_luo/archive/2005/10/25/484861.aspx
I have made a little helper class (based on the codeproject article) that can be used to replace MethodInfo.Invoke, PropertyInfo.GetValue, PropertyInfo.SetValue and Activator.CreateInstance that are the reflection methods that I use most often. In order to use it in your own projects, remember to cache the delegates obtained because every time you call the CreateDelegate the MSIL generation takes place and that takes some time.
I have also created a simple test to show a comparison between direct calls, reflection calls and dynamic method calls. The results are here:
------ Object Creation ------direct - object creation: 63msdynamic method - object creation: 86msreflection - object creation: 391ms------ Property Get ------direct - property get: 21msdynamic method - property get: 81msreflection - property get: 1849ms------ Property Set ------direct - property set: 21msdynamic method - property set: 67msreflection - property set: 2476ms------ Instance Method Call ------direct - instance method call: 24msdynamic method - instance method call: 154msreflection - instance method call: 3266ms------ Static Method Call ------direct - static method call: 36msdynamic method - static method call: 157msreflection - static method call: 3139ms
To summarize: • For object creation, using reflection is 6.2 times slower than direct object creation. With DynamicMethods is only 1.3 times slower than direct object creation. Using DynamicMethods is about 4.5 times faster than using reflection.• To get a property using reflection is 90.1 times slower than direct property access. With DynamicMethods is only 3.8 times slower than direct property access. Using DynamicMethods is nearly 23 times faster than using reflection.• To set a property using reflection is 117.9 times slower than direct property set. With DynamicMethods is only 3.2 times slower than direct property set. Using DynamicMethods is about 37 times faster than using reflection.• For instance method invocation, using reflection is 136.1 times slower than direct method call. With DynamicMethods is only 6.4 times slower than direct method call. Using DynamicMethods is about 21 times faster than using reflection.• For static method invocation, using reflection is 87.2 times slower than direct method call. With DynamicMethods is only 4.3 times slower than direct method call. Using DynamicMethods is about 20 times faster than using reflection.
I’m going to modify my ExtendedObjectDataSource to use DynamicMethods in order to gain a 20x speed increase compared to reflection calls.
The code used for the tests and the helper class for the DynamicMethods are shown here and can be downloaded at the end of this post:
using System;
using System.Reflection;
using System.Reflection.Emit;
namespace Manu.Utils
{
/// <summary>Delegate for calling a method that is not known at runtime.</summary>
/// <param name="target">the object to be called or null if the call is to a static method.</param>
/// <param name="paramters">the parameters to the method.</param>
/// <returns>the return value for the method or null if it doesn't return anything.</returns>
public delegate object FastInvokeHandler(object target, object[] parameters);
/// <summary>Delegate for creating and object at runtime using the default constructor.</summary>
/// <returns>the newly created object.</returns>
public delegate object FastCreateInstanceHandler();
/// <summary>Delegate to get an arbitraty property at runtime.</summary>
/// <param name="target">the object instance whose property will be obtained.</param>
/// <returns>the property value.</returns>
public delegate object FastPropertyGetHandler(object target);
/// <summary>Delegate to set an arbitrary property at runtime.</summary>
/// <param name="target">the object instance whose property will be modified.</param>
/// <param name="parameter"></param>
public delegate void FastPropertySetHandler(object target, object parameter);
/// <summary>Class with helper methods for dynamic invocation generating IL on the fly.</summary>
public static class DynamicCalls
public static FastInvokeHandler GetMethodInvoker(MethodInfo methodInfo)
// generates a dynamic method to generate a FastInvokeHandler delegate
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object), typeof(object[]) }, methodInfo.DeclaringType.Module);
ILGenerator ilGenerator = dynamicMethod.GetILGenerator();
ParameterInfo[] parameters = methodInfo.GetParameters();
Type[] paramTypes = new Type[parameters.Length];
// copies the parameter types to an array
for (int i = 0; i < paramTypes.Length; i++) {
if (parameters[i].ParameterType.IsByRef)
paramTypes[i] = parameters[i].ParameterType.GetElementType();
else
paramTypes[i] = parameters[i].ParameterType;
}
LocalBuilder[] locals = new LocalBuilder[paramTypes.Length];
// generates a local variable for each parameter
locals[i] = ilGenerator.DeclareLocal(paramTypes[i], true);
// creates code to copy the parameters to the local variables
ilGenerator.Emit(OpCodes.Ldarg_1);
EmitFastInt(ilGenerator, i);
ilGenerator.Emit(OpCodes.Ldelem_Ref);
EmitCastToReference(ilGenerator, paramTypes[i]);
ilGenerator.Emit(OpCodes.Stloc, locals[i]);
if (!methodInfo.IsStatic) {
// loads the object into the stack
ilGenerator.Emit(OpCodes.Ldarg_0);
// loads the parameters copied to the local variables into the stack
ilGenerator.Emit(OpCodes.Ldloca_S, locals[i]);
ilGenerator.Emit(OpCodes.Ldloc, locals[i]);
// calls the method
ilGenerator.EmitCall(OpCodes.Callvirt, methodInfo, null);
} else {
ilGenerator.EmitCall(OpCodes.Call, methodInfo, null);
// creates code for handling the return value
if (methodInfo.ReturnType == typeof(void)) {
ilGenerator.Emit(OpCodes.Ldnull);
EmitBoxIfNeeded(ilGenerator, methodInfo.ReturnType);
// iterates through the parameters updating the parameters passed by ref
if (parameters[i].ParameterType.IsByRef) {
if (locals[i].LocalType.IsValueType)
ilGenerator.Emit(OpCodes.Box, locals[i].LocalType);
ilGenerator.Emit(OpCodes.Stelem_Ref);
// returns the value to the caller
ilGenerator.Emit(OpCodes.Ret);
// converts the DynamicMethod to a FastInvokeHandler delegate to call to the method
FastInvokeHandler invoker = (FastInvokeHandler)dynamicMethod.CreateDelegate(typeof(FastInvokeHandler));
return invoker;
/// <summary>Gets the instance creator delegate that can be use to create instances of the specified type.</summary>
/// <param name="type">The type of the objects we want to create.</param>
/// <returns>A delegate that can be used to create the objects.</returns>
public static FastCreateInstanceHandler GetInstanceCreator(Type type)
// generates a dynamic method to generate a FastCreateInstanceHandler delegate
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, type, new Type[0], typeof(DynamicCalls).Module);
// generates code to create a new object of the specified type using the default constructor
ilGenerator.Emit(OpCodes.Newobj, type.GetConstructor(Type.EmptyTypes));
// converts the DynamicMethod to a FastCreateInstanceHandler delegate to create the object
FastCreateInstanceHandler creator = (FastCreateInstanceHandler)dynamicMethod.CreateDelegate(typeof(FastCreateInstanceHandler));
return creator;
public static FastPropertyGetHandler GetPropertyGetter(PropertyInfo propInfo)
// generates a dynamic method to generate a FastPropertyGetHandler delegate
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, typeof(object), new Type[] { typeof(object) }, propInfo.DeclaringType.Module);
// calls the getter
ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetGetMethod(), null);
EmitBoxIfNeeded(ilGenerator, propInfo.PropertyType);
// converts the DynamicMethod to a FastPropertyGetHandler delegate to get the property
FastPropertyGetHandler getter = (FastPropertyGetHandler)dynamicMethod.CreateDelegate(typeof(FastPropertyGetHandler));
return getter;
public static FastPropertySetHandler GetPropertySetter(PropertyInfo propInfo)
// generates a dynamic method to generate a FastPropertySetHandler delegate
DynamicMethod dynamicMethod = new DynamicMethod(string.Empty, null, new Type[] { typeof(object), typeof(object) }, propInfo.DeclaringType.Module);
// loads the parameter from the stack
// cast to the proper type (unboxing if needed)
EmitCastToReference(ilGenerator, propInfo.PropertyType);
// calls the setter
ilGenerator.EmitCall(OpCodes.Callvirt, propInfo.GetSetMethod(), null);
// terminates the call
FastPropertySetHandler setter = (FastPropertySetHandler)dynamicMethod.CreateDelegate(typeof(FastPropertySetHandler));
return setter;
/// <summary>Emits the cast to a reference, unboxing if needed.</summary>
/// <param name="il">The MSIL generator.</param>
/// <param name="type">The type to cast.</param>
private static void EmitCastToReference(ILGenerator ilGenerator, System.Type type)
if (type.IsValueType) {
ilGenerator.Emit(OpCodes.Unbox_Any, type);
ilGenerator.Emit(OpCodes.Castclass, type);
/// <summary>Boxes a type if needed.</summary>
/// <param name="ilGenerator">The MSIL generator.</param>
/// <param name="type">The type.</param>
private static void EmitBoxIfNeeded(ILGenerator ilGenerator, System.Type type)
ilGenerator.Emit(OpCodes.Box, type);
/// <summary>Emits code to save an integer to the evaluation stack.</summary>
/// <param name="ilGeneartor">The MSIL generator.</param>
/// <param name="value">The value to push.</param>
private static void EmitFastInt(ILGenerator ilGenerator, int value)
// for small integers, emit the proper opcode
switch (value) {
case -1:
ilGenerator.Emit(OpCodes.Ldc_I4_M1);
return;
case 0:
ilGenerator.Emit(OpCodes.Ldc_I4_0);
case 1:
ilGenerator.Emit(OpCodes.Ldc_I4_1);
case 2:
ilGenerator.Emit(OpCodes.Ldc_I4_2);
case 3:
ilGenerator.Emit(OpCodes.Ldc_I4_3);
case 4:
ilGenerator.Emit(OpCodes.Ldc_I4_4);
case 5:
ilGenerator.Emit(OpCodes.Ldc_I4_5);
case 6:
ilGenerator.Emit(OpCodes.Ldc_I4_6);
case 7:
ilGenerator.Emit(OpCodes.Ldc_I4_7);
case 8:
ilGenerator.Emit(OpCodes.Ldc_I4_8);
// for bigger values emit the short or long opcode
if (value > -129 && value < 128) {
ilGenerator.Emit(OpCodes.Ldc_I4_S, (SByte)value);
ilGenerator.Emit(OpCodes.Ldc_I4, value);
using System.Collections.Generic;
using System.Diagnostics;
using Manu.Utils;
namespace DynamicMethods
public class Program
public static void Main(string[] args)
// object creation
Console.WriteLine("------ Object Creation ------");
EvaluateMethod("direct - object creation", delegate() {
TestClass p = new TestClass();
}, 1000000);
FastCreateInstanceHandler creator = DynamicCalls.GetInstanceCreator(typeof(TestClass));
EvaluateMethod("dynamic method - object creation", delegate() {
TestClass p = (TestClass)creator.Invoke();
EvaluateMethod("reflection - object creation", delegate() {
TestClass p = (TestClass)Activator.CreateInstance(typeof(TestClass));
// property get
Console.WriteLine("------ Property Get ------");
TestClass prod = new TestClass();
prod.Num = 123;
EvaluateMethod("direct - property get", delegate() {
int num = prod.Num;
PropertyInfo propInfo = typeof(TestClass).GetProperty("Num");
FastPropertyGetHandler getter = DynamicCalls.GetPropertyGetter(propInfo);
EvaluateMethod("dynamic method - property get", delegate() {
int num = (int)getter(prod);
EvaluateMethod("reflection - property get", delegate() {
int num = (int)propInfo.GetValue(prod, null);
// property set
Console.WriteLine("------ Property Set ------");
EvaluateMethod("direct - property set", delegate() {
prod.Num = 33;
FastPropertySetHandler setter = DynamicCalls.GetPropertySetter(propInfo);
EvaluateMethod("dynamic method - property set", delegate() {
setter(prod, 32);
EvaluateMethod("reflection - property set", delegate() {
propInfo.SetValue(prod, 31, null);
// instance method call
Console.WriteLine("------ Instance Method Call ------");
EvaluateMethod("direct - instance method call", delegate() {
int result = prod.Multiply(3, 5);
MethodInfo methodInfo1 = typeof(TestClass).GetMethod("Multiply");
FastInvokeHandler fastInvoker1 = DynamicCalls.GetMethodInvoker(methodInfo1);
EvaluateMethod("dynamic method - instance method call", delegate() {
int result = (int)fastInvoker1(prod, new object[] { 3, 5 });
EvaluateMethod("reflection - instance method call", delegate() {
int result = (int)methodInfo1.Invoke(prod, new object[] { 3, 5 });
// static method call
Console.WriteLine("------ Static Method Call ------");
EvaluateMethod("direct - static method call", delegate() {
int result = TestClass.StaticMultiply(3, 5);
MethodInfo methodInfo2 = typeof(TestClass).GetMethod("StaticMultiply");
FastInvokeHandler fastInvoker2 = DynamicCalls.GetMethodInvoker(methodInfo2);
EvaluateMethod("dynamic method - static method call", delegate() {
int result = (int)fastInvoker2(null, new object[] { 3, 5 });
EvaluateMethod("reflection - static method call", delegate() {
int result = (int)methodInfo2.Invoke(null, new object[] { 3, 5 });
Console.ReadLine();
delegate void MethodToEvaluate();
// evaluates a method the specified number of times and print performance information
static void EvaluateMethod(string testName, MethodToEvaluate method, long times)
Stopwatch watch = new Stopwatch();
watch.Start();
for (long i = 0; i < times; i++) {
method();
watch.Stop();
Console.WriteLine(testName + ": " + watch.ElapsedMilliseconds + "ms");
DynamicMethods.zip (5.01 KB)
Remember Me