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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
 public class aField<t>
	{
		private T m_Value;
  

        public override string ToString()
        {
            return Value.ToString();
        }
 public interface IEntity
    {
         aField<string> CREUSER
        {
            get;
            set;
        }

http://www.codingday.com;//downloads/reflection.zip;Reflection with dynamicmethod ;.

Code for object

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
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.