Sunday, March 25, 2007

Generic copy object using Lightweight Code Generation

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.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null);
            il.EmitCall(OpCodes.Callvirt, prop.GetSetMethod(), null);
    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

No comments: