Mercurial > pub > bltoolkit
comparison Extensions/JointureAddOn/Emit/DynamicCompilationSpike.cs @ 0:f990fcb411a9
Копия текущей версии из github
| author | cin |
|---|---|
| date | Thu, 27 Mar 2014 21:46:09 +0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:f990fcb411a9 |
|---|---|
| 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 } |
