I was involved in a
discussion on microsoft.public.dotnet.framework.clr regarding reflection and lightweight code generation. The original topic was in regards to a 2x slowdown using reflection in .NET 2.0 over 1.1, which was ultimately recognised as a bug by the Microsoft CLR team. I brought up the possibility of using LCG as an alternative in 2.0, and the one of the contributers presented some good examples of using
Delegate.CreateDelegate. Here I wanted to present a use of LCG to copy all the public read/write properties of any object. The meat of the example was the GenerateCopyDelegate function, as follows:
static CopyPublicPropertiesDelegate<T> GenerateCopyDelegate<T>()
{ Type type = typeof(T);
DynamicMethod dm = new DynamicMethod(type.Name, null, new Type[] { typeof(T), typeof(T) }, typeof(Program).Module);
ILGenerator il = dm.GetILGenerator();
PropertyInfo[] props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (PropertyInfo prop in props)
{ if (prop.CanRead && prop.CanWrite)
{ il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldarg_0);
il.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null);
il.EmitCall(OpCodes.Callvirt, prop.GetSetMethod(), null);
}
}
il.Emit(OpCodes.Ret);
return (CopyPublicPropertiesDelegate<T>)dm.CreateDelegate(typeof(CopyPublicPropertiesDelegate<T>));
}
| Method |
Calls (per iteration) |
Total Calls |
|
Delegate |
get_* |
set_* |
|
| LCG |
1 |
6 |
6 |
13,000,000 |
| Delegate |
12 |
6 |
6 |
24,000,000 |