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 😉
No Comments Yet