Reflection for Properties and Fields with DynamicMethod
Lastly I posted about the coolest exception while working with System.Reflection.Dynamicmethod class. I found the solution for my bug, and now it works like a charm. There are two classes for accessing properties or fields, one with the generic implementations and one with object implementation. Using the reflection with dynamicmethod reflection we can get 80% more performance compared to traditional reflection.
Be careful if you are about to use classes that have generic classes as properties. There are some problems with it.
Property that might cause problems of a class
public class aField<T> { private T m_Value; public override string ToString() { return Value.ToString(); } public interface IEntity { aField<string> CREUSER { get; set; }
Code for object
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Reflection.Emit; namespace CE.Reflection { public class DynamicReflectionHelper { public delegate object GetPropertyFieldDelegate(object obj); public static GetPropertyFieldDelegate GetPropertyorField(PropertyInfo pi, FieldInfo fi) { if (pi != null && fi != null) throw new NotSupportedException("one of the parameters should be null"); if (pi != null || fi != null) { string methodName = string.Empty; if (pi != null) methodName = pi.Name; else methodName = fi.Name; Module mod = null; if (pi != null) mod = pi.Module; else mod = fi.Module; DynamicMethod dm = new DynamicMethod("GetPropertyorField_" + methodName, typeof(object), new Type[] { typeof(object) }, mod, true); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); if (pi != null) { il.EmitCall(OpCodes.Callvirt, pi.GetGetMethod(), null); if (pi.PropertyType.IsValueType) { il.Emit(OpCodes.Box, pi.PropertyType); } } else if (fi != null) { il.Emit(OpCodes.Ldfld, fi); if (fi.FieldType.IsValueType) { il.Emit(OpCodes.Box, fi.FieldType); } } il.Emit(OpCodes.Ret); return (GetPropertyFieldDelegate)dm.CreateDelegate(typeof(GetPropertyFieldDelegate)); } else throw new NullReferenceException("no field or property"); } public static GetPropertyFieldDelegate GetPropertyorField(object o, string memberName) { Type v = o.GetType(); PropertyInfo pi = v.GetProperty(memberName); FieldInfo fi = v.GetField(memberName); return GetPropertyorField(pi, fi); } public delegate void SetPropertyFieldDelegate(object obj, object m_Value); public static SetPropertyFieldDelegate SetProperyorField(object o, string memberName) { Type v = o.GetType(); PropertyInfo pi = v.GetProperty(memberName); FieldInfo fi = v.GetField(memberName); return SetProperyorField(pi, fi); } public static SetPropertyFieldDelegate SetProperyorField(PropertyInfo pi, FieldInfo fi) { if (pi != null && fi != null) throw new NotSupportedException("one of the parameters should be null"); if (pi != null || fi != null) { string methodName = string.Empty; if (pi != null) methodName = pi.Name; else methodName = fi.Name; DynamicMethod dm = new DynamicMethod("SetPropertyorField_" + methodName, typeof(void), new Type[] { typeof(object), typeof(object) }, pi.Module, true); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (pi != null) { il.EmitCall(OpCodes.Callvirt, pi.GetSetMethod(true), null); if (pi.PropertyType.IsValueType) { il.Emit(OpCodes.Unbox_Any, pi.PropertyType); } } else { il.Emit(OpCodes.Stfld, fi); if (pi.PropertyType.IsValueType) { il.Emit(OpCodes.Unbox_Any, pi.PropertyType); } } il.Emit(OpCodes.Ret); return (SetPropertyFieldDelegate)dm.CreateDelegate(typeof(SetPropertyFieldDelegate)); } else { throw new NullReferenceException("no field or property"); } } } }
Code for generic object
using System; using System.Collections.Generic; using System.Text; using System.Reflection; using System.Reflection.Emit; namespace CE.Reflection { public class DynamicReflectionHelperforObject<V> { public delegate T GetPropertyFieldDelegate<T>(V obj); public static GetPropertyFieldDelegate<C> GetP<C>(string memberName) { Type v = typeof(V); PropertyInfo pi = v.GetProperty(memberName); FieldInfo fi = v.GetField(memberName); if (pi != null || fi != null) { DynamicMethod dm = new DynamicMethod("GetPropertyorField_" + memberName, typeof(C), new Type[] { v }, v.Module); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); // loaded c, c is the return value if (pi != null) il.EmitCall(OpCodes.Call, pi.GetGetMethod(), null); else if (fi != null) il.Emit(OpCodes.Ldfld, fi); il.Emit(OpCodes.Ret); return (GetPropertyFieldDelegate<C>)dm.CreateDelegate(typeof(GetPropertyFieldDelegate<C>)); } else throw new NullReferenceException("No Property or Field"); } public delegate void SetPropertyFieldDelegate<T>(V obj, T m_Value); public static SetPropertyFieldDelegate<C> SetP<C>(string memberName, C mValue) { Type v = typeof(V); PropertyInfo pi = v.GetProperty(memberName); FieldInfo fi = v.GetField(memberName); if (pi != null || fi != null) { DynamicMethod dm = new DynamicMethod("SetPropertyorField_" + memberName, typeof(void), new Type[] { v, typeof(C) }, v.Module); ILGenerator il = dm.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldarg_1); if (pi != null) il.EmitCall(OpCodes.Callvirt, pi.GetSetMethod(), new Type[] { typeof(C) }); else if (fi != null) il.Emit(OpCodes.Stfld, fi); il.Emit(OpCodes.Ret); return (SetPropertyFieldDelegate<C>)dm.CreateDelegate(typeof(SetPropertyFieldDelegate<C>)); } else throw new NullReferenceException("No Property or Field"); } } }
This project has two main classes, one is generic for working with a specified type, and the other is normal object class in which you need to deal with conversion after using it.



Hi,
Great code. However, in your sample for creating the setter, you have inverted the set operations. You need to unbox (if necessary) prior to setting the value, not after.
Thanks again…
29 January 2007, 8:10 pmHi,
30 January 2007, 2:00 amThank you for feedback, you are absolutely right. I just fixed it. I post the code with the samples.
yess great work, but remove turkish exception text like: “Böyle bi property field yok”
16 February 2007, 12:31 pmThank you for your feedback.
I changed it.
16 February 2007, 3:44 pm