andrew4582

LateBoundDelegateFactory

Aug 15th, 2010
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 8.12 KB | None | 0 0
  1. #if !PocketPC
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Reflection;
  6. using System.Reflection.Emit;
  7. using System.Text;
  8. using System.Globalization;
  9.  
  10. namespace System.Utilities
  11. {
  12.   internal static class LateBoundDelegateFactory
  13.   {
  14.     public static Func<T, object> CreateGet<T>(MemberInfo memberInfo)
  15.     {
  16.       PropertyInfo propertyInfo = memberInfo as PropertyInfo;
  17.       if (propertyInfo != null)
  18.         return CreateGet<T>(propertyInfo);
  19.  
  20.       FieldInfo fieldInfo = memberInfo as FieldInfo;
  21.       if (fieldInfo != null)
  22.         return CreateGet<T>(fieldInfo);
  23.  
  24.       throw new Exception("Could not create getter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
  25.     }
  26.  
  27.     private static DynamicMethod CreateDynamicMethod(string name, Type returnType, Type[] parameterTypes, Type owner)
  28.     {
  29.       DynamicMethod dynamicMethod = !owner.IsInterface
  30.         ? new DynamicMethod(name, returnType, parameterTypes, owner, true)
  31.         : new DynamicMethod(name, returnType, parameterTypes, (Module)null, true);
  32.  
  33.       return dynamicMethod;
  34.     }
  35.  
  36.     public static Action<T, object> CreateSet<T>(MemberInfo memberInfo)
  37.     {
  38.       PropertyInfo propertyInfo = memberInfo as PropertyInfo;
  39.       if (propertyInfo != null)
  40.         return CreateSet<T>(propertyInfo);
  41.  
  42.       FieldInfo fieldInfo = memberInfo as FieldInfo;
  43.       if (fieldInfo != null)
  44.         return CreateSet<T>(fieldInfo);
  45.  
  46.       throw new Exception("Could not create setter for {0}.".FormatWith(CultureInfo.InvariantCulture, memberInfo));
  47.     }
  48.  
  49.     public static MemberHandler<object> CreateMethodHandler(MethodBase method)
  50.     {
  51.       DynamicMethod dynamicMethod = CreateDynamicMethod(method.ToString(), typeof(object), new[] { typeof(object), typeof(object[]) }, method.DeclaringType);
  52.       ILGenerator generator = dynamicMethod.GetILGenerator();
  53.  
  54.       ParameterInfo[] args = method.GetParameters();
  55.  
  56.       Label argsOk = generator.DefineLabel();
  57.  
  58.       generator.Emit(OpCodes.Ldarg_1);
  59.       generator.Emit(OpCodes.Ldlen);
  60.       generator.Emit(OpCodes.Ldc_I4, args.Length);
  61.       generator.Emit(OpCodes.Beq, argsOk);
  62.  
  63.       generator.Emit(OpCodes.Newobj, typeof(TargetParameterCountException).GetConstructor(Type.EmptyTypes));
  64.       generator.Emit(OpCodes.Throw);
  65.  
  66.       generator.MarkLabel(argsOk);
  67.  
  68.       if (!method.IsConstructor)
  69.         generator.PushInstance(method.DeclaringType);
  70.  
  71.       for (int i = 0; i < args.Length; i++)
  72.       {
  73.         generator.Emit(OpCodes.Ldarg_1);
  74.         generator.Emit(OpCodes.Ldc_I4, i);
  75.         generator.Emit(OpCodes.Ldelem_Ref);
  76.  
  77.         generator.UnboxIfNeeded(args[i].ParameterType);
  78.       }
  79.  
  80.       if (method.IsConstructor)
  81.         generator.Emit(OpCodes.Newobj, (ConstructorInfo)method);
  82.       else if (method.IsFinal || !method.IsVirtual)
  83.         generator.Emit(OpCodes.Call, (MethodInfo)method);
  84.       else
  85.         generator.Emit(OpCodes.Callvirt, (MethodInfo)method);
  86.  
  87.       Type returnType = method.IsConstructor
  88.         ? method.DeclaringType
  89.         : ((MethodInfo)method).ReturnType;
  90.  
  91.       if (returnType != typeof(void))
  92.         generator.BoxIfNeeded(returnType);
  93.       else
  94.         generator.Emit(OpCodes.Ldnull);
  95.  
  96.       generator.Emit(OpCodes.Ret);
  97.  
  98.       return (MemberHandler<object>)dynamicMethod.CreateDelegate(typeof(MemberHandler<object>));
  99.     }
  100.  
  101.  
  102.     public static Func<object> CreateDefaultConstructor(Type type)
  103.     {
  104.       DynamicMethod dynamicMethod = CreateDynamicMethod("Create" + type.FullName, typeof(object), Type.EmptyTypes, type);
  105.       dynamicMethod.InitLocals = true;
  106.       ILGenerator generator = dynamicMethod.GetILGenerator();
  107.  
  108.       if (type.IsValueType)
  109.       {
  110.         generator.DeclareLocal(type);
  111.         generator.Emit(OpCodes.Ldloc_0);
  112.         generator.Emit(OpCodes.Box, type);
  113.       }
  114.       else
  115.       {
  116.         ConstructorInfo constructorInfo =
  117.           type.GetConstructor(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance, null,
  118.                               Type.EmptyTypes, null);
  119.  
  120.         if (constructorInfo == null)
  121.           throw new Exception("Could not get constructor for {0}.".FormatWith(CultureInfo.InvariantCulture, type));
  122.  
  123.         generator.Emit(OpCodes.Newobj, constructorInfo);
  124.       }
  125.  
  126.       generator.Emit(OpCodes.Ret);
  127.  
  128.       return (Func<object>)dynamicMethod.CreateDelegate(typeof(Func<object>));
  129.     }
  130.  
  131.     public static Func<T, object> CreateGet<T>(PropertyInfo propertyInfo)
  132.     {
  133.       MethodInfo getMethod = propertyInfo.GetGetMethod(true);
  134.       if (getMethod == null)
  135.         throw new Exception("Property '{0}' does not have a getter.".FormatWith(CultureInfo.InvariantCulture,
  136.                                                                                 propertyInfo.Name));
  137.  
  138.       DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + propertyInfo.Name, typeof(T), new[] { typeof(object) }, propertyInfo.DeclaringType);
  139.  
  140.       ILGenerator generator = dynamicMethod.GetILGenerator();
  141.  
  142.       if (!getMethod.IsStatic)
  143.         generator.PushInstance(propertyInfo.DeclaringType);
  144.  
  145.       if (getMethod.IsFinal || !getMethod.IsVirtual)
  146.         generator.Emit(OpCodes.Call, getMethod);
  147.       else
  148.         generator.Emit(OpCodes.Callvirt, getMethod);
  149.  
  150.       generator.BoxIfNeeded(propertyInfo.PropertyType);
  151.       generator.Emit(OpCodes.Ret);
  152.  
  153.       return (Func<T, object>)dynamicMethod.CreateDelegate(typeof(Func<T, object>));
  154.     }
  155.  
  156.     static void PushInstance(this ILGenerator generator, Type type)
  157.     {
  158.       generator.Emit(OpCodes.Ldarg_0);
  159.       if (type.IsValueType)
  160.         generator.Emit(OpCodes.Unbox, type);
  161.     }
  162.  
  163.     static void BoxIfNeeded(this ILGenerator generator, Type type)
  164.     {
  165.       if (type.IsValueType)
  166.         generator.Emit(OpCodes.Box, type);
  167.     }
  168.  
  169.     static void UnboxIfNeeded(this ILGenerator generator, Type type)
  170.     {
  171.       if (type.IsValueType)
  172.         generator.Emit(OpCodes.Unbox_Any, type);
  173.     }
  174.  
  175.     public static Func<T, object> CreateGet<T>(FieldInfo fieldInfo)
  176.     {
  177.       DynamicMethod dynamicMethod = CreateDynamicMethod("Get" + fieldInfo.Name, typeof(T), new[] { typeof(object) }, fieldInfo.DeclaringType);
  178.  
  179.       ILGenerator generator = dynamicMethod.GetILGenerator();
  180.  
  181.       if (!fieldInfo.IsStatic)
  182.         generator.PushInstance(fieldInfo.DeclaringType);
  183.  
  184.       generator.Emit(OpCodes.Ldfld, fieldInfo);
  185.       generator.BoxIfNeeded(fieldInfo.FieldType);
  186.       generator.Emit(OpCodes.Ret);
  187.  
  188.       return (Func<T, object>)
  189.           dynamicMethod.CreateDelegate(typeof(Func<T, object>));
  190.     }
  191.  
  192.     public static Action<T, object> CreateSet<T>(FieldInfo fieldInfo)
  193.     {
  194.       DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + fieldInfo.Name, null, new[] { typeof(object), typeof(object) }, fieldInfo.DeclaringType);
  195.       ILGenerator generator = dynamicMethod.GetILGenerator();
  196.  
  197.       if (!fieldInfo.IsStatic)
  198.         generator.PushInstance(fieldInfo.DeclaringType);
  199.  
  200.       generator.Emit(OpCodes.Ldarg_1);
  201.       generator.UnboxIfNeeded(fieldInfo.FieldType);
  202.       generator.Emit(OpCodes.Stfld, fieldInfo);
  203.       generator.Emit(OpCodes.Ret);
  204.  
  205.       return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
  206.     }
  207.  
  208.     public static Action<T, object> CreateSet<T>(PropertyInfo propertyInfo)
  209.     {
  210.       MethodInfo getMethod = propertyInfo.GetSetMethod(true);
  211.       DynamicMethod dynamicMethod = CreateDynamicMethod("Set" + propertyInfo.Name, null, new[] { typeof(object), typeof(object) }, propertyInfo.DeclaringType);
  212.       ILGenerator generator = dynamicMethod.GetILGenerator();
  213.  
  214.       if (!getMethod.IsStatic)
  215.         generator.PushInstance(propertyInfo.DeclaringType);
  216.  
  217.       generator.Emit(OpCodes.Ldarg_1);
  218.       generator.UnboxIfNeeded(propertyInfo.PropertyType);
  219.  
  220.       if (getMethod.IsFinal || !getMethod.IsVirtual)
  221.         generator.Emit(OpCodes.Call, getMethod);
  222.       else
  223.         generator.Emit(OpCodes.Callvirt, getMethod);
  224.  
  225.       generator.Emit(OpCodes.Ret);
  226.  
  227.       return (Action<T, object>)dynamicMethod.CreateDelegate(typeof(Action<T, object>));
  228.     }
  229.   }
  230. }
  231. #endif
Advertisement
Add Comment
Please, Sign In to add comment