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…
Hi,
Thank you for feedback, you are absolutely right. I just fixed it. I post the code with the samples.
yess great work, but pls remove some exception text like
Thank you for your feedback.
I changed it.
DynamicMethod dm = new DynamicMethod(“SetPropertyorField_” +
methodName, typeof(void),
new Type[] { typeof(object), typeof(object) }, pi.Module, true);
In SetProperyorField(), the above line directly uses pi.Module. Pi could be null right?
Also the following code uses pi.PropertyType instead of fi.FieldType
il.Emit(OpCodes.Stfld, fi);
if (pi.PropertyType.IsValueType)
{
il.Emit(OpCodes.Unbox_Any, pi.PropertyType);
}
Can i access an internal property from an external assembly? (Using Reflection)
yes it should be possible, as long as you have referenced the assembly
Fascinating code.
I saw tiny bug though in the first example’s ‘SetProperyorField(PropertyInfo pi, FieldInfo fi)’ that code passes in ‘pi.Module’ but ‘pi’ may be null (this is handled correctly in the partner method above it). I wonder why we see such poor peformance from .Net and its reflection access, when they could have provided stuff like this ‘out of the box’?
Hugh