annotate Extensions/JointureAddOn/Emit/DynamicCompilationSpike.cs @ 0:f990fcb411a9

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