Using reflection to invoke methods which are not known at compile time might be problematic in performance critical applications. It is roughly 2.5-3.0 times slower than direct method calls. Here’s a sample test I’ve conducted:
class Program { [DllImport("kernel32.dll")] static extern void QueryPerformanceCounter(ref long ticks); static PropertyInfo _intProp = typeof(Foo).GetProperty("IntProp", BindingFlags.Public | BindingFlags.Instance); static void Main(string[] args) { Foo foo = new Foo { IntProp = 10 }; const int COUNT = 1; Console.WriteLine(Measure(() => ReadPropertyWithReflection(foo), COUNT)); Console.WriteLine(Measure(() => ReadPropertyDirectly(foo), COUNT)); } static void ReadPropertyWithReflection(Foo foo) { int intProp = (int)_intProp.GetValue(foo, null); } static void ReadPropertyDirectly(Foo foo) { int intProp = foo.IntProp; } static long Measure(Action action, int count) { long startTicks = 0; QueryPerformanceCounter(ref startTicks); for (int i = 0; i < count; i++) { action(); } long endTicks = 0; QueryPerformanceCounter(ref endTicks); return endTicks - startTicks; } class Foo { public int IntProp { get; set; } } }
Here are the results:
Method | CPU units |
Direct method invocation | 796 |
Reflection method invocation | 1986 |
So using reflection to perform a single property read is 2.5 slower than direct property access.
Dynamic methods can be used to generate and execute a method at run time, without having to declare a dynamic assembly and a dynamic type to contain the method. They are the most efficient way to generate and execute small amounts of code. Here’s an example of using DynamicMethod class to generate a getter for a given property:
static Func<Arg0, TReturn> EmitGetter<Arg0, TReturn>(PropertyInfo propertyInfo) { MethodInfo mi = propertyInfo.GetGetMethod(); DynamicMethod dm = new DynamicMethod( "_get", typeof(TReturn), new Type[] { typeof(Arg0) }, propertyInfo.DeclaringType); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Castclass, propertyInfo.DeclaringType); il.EmitCall(OpCodes.Callvirt, mi, null); il.Emit(OpCodes.Ret); return (Func<Arg0, TReturn>)dm.CreateDelegate(typeof(Func<Arg0, TReturn>)); }
Now using this method we can emit a getter method from a PropertyInfo at run time and execute the returned delegate:
Func<Foo, int> getter = EmitGetter<Foo, int>(_intProp); Console.WriteLine(Measure(() => getter(foo), COUNT));
And here are the final results I’ve obtained using three different methods to read a property value:
Method | CPU units |
Direct method invocation | 796 |
Dynamic method invocation | 1190 |
Reflection method invocation | 1986 |