How often do we developers have to create functions just to copy properties from one object to another object, just because it’s a different type? If the source and destination type have properties with the same name and are of the same type, you can use Lightweight Code Generation to create a delegate to do just that.

As with all programming logic there is a pro and a con to using LCG to do this. Pro, it’s fast because you use compiled code after you’ve built the delegate. Con, it takes a bit of time to create this delegate. I’d use this approach when I will surely need to call this copying function a lot.

Anyway, without further ado.. This is the function I’ve cooked up. (and I’m sorry but the comments are in dutch… 🙂 )

public static CopyPublicPropertiesDelegate GenerateCopyDelegate()
{
Type typeIn = typeof(T);
Type typeOut = typeof(U);

DynamicMethod dm = new DynamicMethod(typeIn.Name, null, new Type[] { typeof(T), typeof(U) }, typeof(GenericCopyObject).Module);

ILGenerator il = dm.GetILGenerator();

PropertyInfo[] propsIn = typeIn.GetProperties(BindingFlags.Public | BindingFlags.Instance);
PropertyInfo[] propsOut = typeOut.GetProperties(BindingFlags.Public | BindingFlags.Instance);

List ps = new List();

foreach (PropertyInfo prop in propsIn) // voor alle properties op het In object
{
PropertyInfo propOut = propsOut.FirstOrDefault
(t => t.Name.Equals(prop.Name) && (t.PropertyType.Equals(prop.PropertyType));
if (propOut != default(PropertyInfo)) // er is een property op het out object met dezelfde naam en type
if (prop.CanRead && propOut.CanWrite) // als we op de bron kunnen lezen en op het doel kunnen schrijven kunnen we kopieren
{
// nu een stukje Assembler...
il.Emit(OpCodes.Ldarg_1);   // Plaats het doelobject op de stack
il.Emit(OpCodes.Ldarg_0);   // Plaats het bronobject op de stack
il.EmitCall(OpCodes.Callvirt, prop.GetGetMethod(), null); // Haal het eerste element (bronobject) van de stack af en lees de waarde uit van de property
il.EmitCall(OpCodes.Callvirt, propOut.GetSetMethod(), null);// Haal het eerste element (doelobject) van de stack af en schrijf de waarde naar de property
}
}
il.Emit(OpCodes.Ret); // we zijn klaar dus de methode mag dan eindigen
return (CopyPublicPropertiesDelegate)dm.CreateDelegate(typeof(CopyPublicPropertiesDelegate));
}

The code needs a small warning though, it won’t work with properties with the same name but a different type and generic types are also quite tricky.

I’m still working on a fix for it, and I’m open for suggestions 😉