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

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Extensions/JointureAddOn/Emit/DynamicCompilationSpike.cs	Thu Mar 27 21:46:09 2014 +0400
@@ -0,0 +1,129 @@
+using System;
+using System.Reflection;
+using System.Reflection.Emit;
+
+namespace BLToolkit.Emit
+{
+    public delegate object GetHandler(object source);
+
+    public delegate void SetHandler(object source, object value);
+
+    public delegate object InstantiateObjectHandler();
+
+    public static class DynamicMethodCompiler
+    {
+        // DynamicMethodCompiler
+
+        // CreateInstantiateObjectDelegate
+        internal static InstantiateObjectHandler CreateInstantiateObjectHandler(Type type)
+        {
+            ConstructorInfo constructorInfo =
+                type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
+                                    new Type[0], null);
+            if (constructorInfo == null)
+            {
+                throw new ApplicationException(
+                    string.Format(
+                        "The type {0} must declare an empty constructor (the constructor may be private, internal, protected, protected internal, or public).",
+                        type));
+            }
+
+            var dynamicMethod = new DynamicMethod("InstantiateObject", MethodAttributes.Static | MethodAttributes.Public,
+                                                  CallingConventions.Standard, typeof(object), null, type, true);
+            ILGenerator generator = dynamicMethod.GetILGenerator();
+            generator.Emit(OpCodes.Newobj, constructorInfo);
+            generator.Emit(OpCodes.Ret);
+            return (InstantiateObjectHandler)dynamicMethod.CreateDelegate(typeof(InstantiateObjectHandler));
+        }
+
+        // CreateGetDelegate
+        internal static GetHandler CreateGetHandler(Type type, PropertyInfo propertyInfo)
+        {
+            MethodInfo getMethodInfo = propertyInfo.GetGetMethod(true);
+            DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
+            ILGenerator getGenerator = dynamicGet.GetILGenerator();
+
+            getGenerator.Emit(OpCodes.Ldarg_0);
+            getGenerator.Emit(OpCodes.Call, getMethodInfo);
+            BoxIfNeeded(getMethodInfo.ReturnType, getGenerator);
+            getGenerator.Emit(OpCodes.Ret);
+
+            return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
+        }
+
+        // CreateGetDelegate
+        internal static GetHandler CreateGetHandler(Type type, FieldInfo fieldInfo)
+        {
+            DynamicMethod dynamicGet = CreateGetDynamicMethod(type);
+            ILGenerator getGenerator = dynamicGet.GetILGenerator();
+
+            getGenerator.Emit(OpCodes.Ldarg_0);
+            getGenerator.Emit(OpCodes.Ldfld, fieldInfo);
+            BoxIfNeeded(fieldInfo.FieldType, getGenerator);
+            getGenerator.Emit(OpCodes.Ret);
+
+            return (GetHandler)dynamicGet.CreateDelegate(typeof(GetHandler));
+        }
+
+        // CreateSetDelegate
+        internal static SetHandler CreateSetHandler(Type type, PropertyInfo propertyInfo)
+        {
+            MethodInfo setMethodInfo = propertyInfo.GetSetMethod(true);
+            DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
+            ILGenerator setGenerator = dynamicSet.GetILGenerator();
+
+            setGenerator.Emit(OpCodes.Ldarg_0);
+            setGenerator.Emit(OpCodes.Ldarg_1);
+            UnboxIfNeeded(setMethodInfo.GetParameters()[0].ParameterType, setGenerator);
+            setGenerator.Emit(OpCodes.Call, setMethodInfo);
+            setGenerator.Emit(OpCodes.Ret);
+
+            return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
+        }
+
+        // CreateSetDelegate
+        internal static SetHandler CreateSetHandler(Type type, FieldInfo fieldInfo)
+        {
+            DynamicMethod dynamicSet = CreateSetDynamicMethod(type);
+            ILGenerator setGenerator = dynamicSet.GetILGenerator();
+
+            setGenerator.Emit(OpCodes.Ldarg_0);
+            setGenerator.Emit(OpCodes.Ldarg_1);
+            UnboxIfNeeded(fieldInfo.FieldType, setGenerator);
+            setGenerator.Emit(OpCodes.Stfld, fieldInfo);
+            setGenerator.Emit(OpCodes.Ret);
+
+            return (SetHandler)dynamicSet.CreateDelegate(typeof(SetHandler));
+        }
+
+        // CreateGetDynamicMethod
+        private static DynamicMethod CreateGetDynamicMethod(Type type)
+        {
+            return new DynamicMethod("DynamicGet", typeof(object), new[] { typeof(object) }, type, true);
+        }
+
+        // CreateSetDynamicMethod
+        private static DynamicMethod CreateSetDynamicMethod(Type type)
+        {
+            return new DynamicMethod("DynamicSet", typeof(void), new[] { typeof(object), typeof(object) }, type, true);
+        }
+
+        // BoxIfNeeded
+        private static void BoxIfNeeded(Type type, ILGenerator generator)
+        {
+            if (type.IsValueType)
+            {
+                generator.Emit(OpCodes.Box, type);
+            }
+        }
+
+        // UnboxIfNeeded
+        private static void UnboxIfNeeded(Type type, ILGenerator generator)
+        {
+            if (type.IsValueType)
+            {
+                generator.Emit(OpCodes.Unbox_Any, type);
+            }
+        }
+    }
+}
\ No newline at end of file