Advertisement
Inverness

TypeUtility.cs

May 12th, 2014
229
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 3.43 KB | None | 0 0
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. using System.Linq.Expressions;
  5. using System.Reflection;
  6.  
  7. namespace Ramp
  8. {
  9.     /// <summary>
  10.     ///     Provides utilities for working with types and reflection.
  11.     /// </summary>
  12.     public static class TypeUtility
  13.     {
  14.         /// <summary>
  15.         ///     Compiles a delegate that invokes a matching constructor for the specified type without reflection.
  16.         /// </summary>
  17.         /// <typeparam name="T"> A delegate type. </typeparam>
  18.         /// <param name="type"> The type to construct. </param>
  19.         /// <returns> A delegate that can be used to construct an instance of the specified type. </returns>
  20.         public static T CreateConstructorDelegate<T>(Type type)
  21.         {
  22.             return (T) (object) CreateConstructorDelegate(typeof(T), type);
  23.         }
  24.  
  25.         /// <summary>
  26.         ///     Compiles a delegate that invokes a matching constructor for the specified type without reflection.
  27.         /// </summary>
  28.         /// <param name="delegateType"> A delegate type. </param>
  29.         /// <param name="constructType"> A type to construct. </param>
  30.         /// <returns> A delegate that can be used to construct an instance of the specified type. </returns>
  31.         public static Delegate CreateConstructorDelegate(Type delegateType, Type constructType)
  32.         {
  33.             if (delegateType == null)
  34.                 throw new ArgumentNullException("delegateType");
  35.             if (constructType == null)
  36.                 throw new ArgumentNullException("constructType");
  37.             if (!typeof(MulticastDelegate).IsAssignableFrom(delegateType))
  38.                 throw new ArgumentOutOfRangeException("delegateType", "must be a delegate");
  39.             if (constructType.IsAbstract)
  40.                 throw new ArgumentOutOfRangeException("constructType", "type must not be abstract");
  41.            
  42.             // The Invoke method will have the return and parameter types we're looking for.
  43.             MethodInfo invoke = delegateType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance);
  44.             if (invoke == null)
  45.                 throw new MissingMethodException(delegateType.FullName, "Invoke method not found");
  46.  
  47.             if (invoke.ReturnType == typeof(void))
  48.                 throw new ArgumentOutOfRangeException("delegateType", "delegate type must not return void");
  49.             if (!invoke.ReturnType.IsAssignableFrom(constructType))
  50.                 throw new ArgumentOutOfRangeException("delegateType", "delegate return type must be assignable from construction type");
  51.  
  52.             ParameterInfo[] parameters = invoke.GetParameters();
  53.             Type[] parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
  54.  
  55.             ConstructorInfo constructor = constructType.GetConstructor(parameterTypes);
  56.             if (constructor == null)
  57.                 throw new MissingMethodException(constructType.FullName, "no constructor found matching delegate parameter types");
  58.  
  59.             // Compile the expression
  60.             ParameterExpression[] parameterExpressions =
  61.                 parameters.Select(pi => Expression.Parameter(pi.ParameterType, pi.Name)).ToArray();
  62.             NewExpression newExpression =
  63.                 Expression.New(constructor, parameterExpressions.Cast<Expression>().ToArray());
  64.             return Expression.Lambda(delegateType, newExpression, parameterExpressions).Compile();
  65.         }
  66.     }
  67. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement