0
|
1 using System;
|
|
2 using System.Reflection;
|
|
3 using System.Reflection.Emit;
|
|
4
|
|
5 namespace BLToolkit.Emit
|
|
6 {
|
|
7 public delegate object GetHandler(object source);
|
|
8
|
|
9 public delegate void SetHandler(object source, object value);
|
|
10
|
|
11 public delegate object InstantiateObjectHandler();
|
|
12
|
|
13 public static class DynamicMethodCompiler
|
|
14 {
|
|
15 // DynamicMethodCompiler
|
|
16
|
|
17 // CreateInstantiateObjectDelegate
|
|
18 internal static InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
|
|
19 {
|
|
20 ConstructorInfo constructorInfo =
|
|
21 type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
|
|
22 new Type[0], null);
|
|
23 if (constructorInfo == null)
|
|
24 {
|
|
25 throw new ApplicationException(
|
|
26 string.Format(
|
|
27 "The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).",
|
|
28 type));
|
|
29 }
|
|
30
|
|
31 var dynamicMethod = new DynamicMethod("InstantiateObject", MethodAttributes.Static | MethodAttributes.Public,
|
|
32 CallingConventions.Standard, typeof(object), null, type, true);
|
|
33 ILGenerator generator = dynamicMethod.GetILGenerator();
|
|
34 generator.Emit(OpCodes.Newobj, constructorInfo);
|
|
35 generator.Emit(OpCodes.Ret);
|
|
36 return (InstantiateObjectHandler)dynamicMethod.CreateDelegate(typeof(InstantiateObjectHandler));
|
|
37 }
|
|
38
|
|
39 // CreateGetDelegate
|
|
40 internal static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
|
|
41 {
|
|
42 MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true);
|
|
43 DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
|
|
44 ILGenerator getGenerator = dynamicGet.GetILGenerator();
|
|
45
|
|
46 getGenerator.Emit(OpCodes.Ldarg_0);
|
|
47 getGenerator.Emit(OpCodes.Call, getMethodInfo);
|
|
48 BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
|
|
49 getGenerator.Emit(OpCodes.Ret);
|
|
50
|
|
51 return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
|
|
52 }
|
|
53
|
|
54 // CreateGetDelegate
|
|
55 internal static GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
|
|
56 {
|
|
57 DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
|
|
58 ILGenerator getGenerator = dynamicGet.GetILGenerator();
|
|
59
|
|
60 getGenerator.Emit(OpCodes.Ldarg_0);
|
|
61 getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
|
|
62 BoxIfNeeded(fieldInfo.FieldType, getGenerator);
|
|
63 getGenerator.Emit(OpCodes.Ret);
|
|
64
|
|
65 return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
|
|
66 }
|
|
67
|
|
68 // CreateSetDelegate
|
|
69 internal static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
|
|
70 {
|
|
71 MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true);
|
|
72 DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
|
|
73 ILGenerator setGenerator = dynamicSet.GetILGenerator();
|
|
74
|
|
75 setGenerator.Emit(OpCodes.Ldarg_0);
|
|
76 setGenerator.Emit(OpCodes.Ldarg_1);
|
|
77 UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
|
|
78 setGenerator.Emit(OpCodes.Call, setMethodInfo);
|
|
79 setGenerator.Emit(OpCodes.Ret);
|
|
80
|
|
81 return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
|
|
82 }
|
|
83
|
|
84 // CreateSetDelegate
|
|
85 internal static SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
|
|
86 {
|
|
87 DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
|
|
88 ILGenerator setGenerator = dynamicSet.GetILGenerator();
|
|
89
|
|
90 setGenerator.Emit(OpCodes.Ldarg_0);
|
|
91 setGenerator.Emit(OpCodes.Ldarg_1);
|
|
92 UnboxIfNeeded(fieldInfo.FieldType, setGenerator);
|
|
93 setGenerator.Emit(OpCodes.Stfld, fieldInfo);
|
|
94 setGenerator.Emit(OpCodes.Ret);
|
|
95
|
|
96 return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
|
|
97 }
|
|
98
|
|
99 // CreateGetDynamicMethod
|
|
100 private static DynamicMethod CreateGetDynamicMethod(Type type)
|
|
101 {
|
|
102 return new DynamicMethod("DynamicGet", typeof(object), new[] { typeof(object) }, type, true);
|
|
103 }
|
|
104
|
|
105 // CreateSetDynamicMethod
|
|
106 private static DynamicMethod CreateSetDynamicMethod(Type type)
|
|
107 {
|
|
108 return new DynamicMethod("DynamicSet", typeof(void), new[] { typeof(object), typeof(object) }, type, true);
|
|
109 }
|
|
110
|
|
111 // BoxIfNeeded
|
|
112 private static void BoxIfNeeded(Type type, ILGenerator generator)
|
|
113 {
|
|
114 if (type.IsValueType)
|
|
115 {
|
|
116 generator.Emit(OpCodes.Box, type);
|
|
117 }
|
|
118 }
|
|
119
|
|
120 // UnboxIfNeeded
|
|
121 private static void UnboxIfNeeded(Type type, ILGenerator generator)
|
|
122 {
|
|
123 if (type.IsValueType)
|
|
124 {
|
|
125 generator.Emit(OpCodes.Unbox_Any, type);
|
|
126 }
|
|
127 }
|
|
128 }
|
|
129 } |