Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Diagnostics;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- namespace Ramp
- {
- /// <summary>
- /// Provides utilities for working with types and reflection.
- /// </summary>
- public static class TypeUtility
- {
- /// <summary>
- /// Compiles a delegate that invokes a matching constructor for the specified type without reflection.
- /// </summary>
- /// <typeparam name="T"> A delegate type. </typeparam>
- /// <param name="type"> The type to construct. </param>
- /// <returns> A delegate that can be used to construct an instance of the specified type. </returns>
- public static T CreateConstructorDelegate<T>(Type type)
- {
- return (T) (object) CreateConstructorDelegate(typeof(T), type);
- }
- /// <summary>
- /// Compiles a delegate that invokes a matching constructor for the specified type without reflection.
- /// </summary>
- /// <param name="delegateType"> A delegate type. </param>
- /// <param name="constructType"> A type to construct. </param>
- /// <returns> A delegate that can be used to construct an instance of the specified type. </returns>
- public static Delegate CreateConstructorDelegate(Type delegateType, Type constructType)
- {
- if (delegateType == null)
- throw new ArgumentNullException("delegateType");
- if (constructType == null)
- throw new ArgumentNullException("constructType");
- if (!typeof(MulticastDelegate).IsAssignableFrom(delegateType))
- throw new ArgumentOutOfRangeException("delegateType", "must be a delegate");
- if (constructType.IsAbstract)
- throw new ArgumentOutOfRangeException("constructType", "type must not be abstract");
- // The Invoke method will have the return and parameter types we're looking for.
- MethodInfo invoke = delegateType.GetMethod("Invoke", BindingFlags.Public | BindingFlags.Instance);
- if (invoke == null)
- throw new MissingMethodException(delegateType.FullName, "Invoke method not found");
- if (invoke.ReturnType == typeof(void))
- throw new ArgumentOutOfRangeException("delegateType", "delegate type must not return void");
- if (!invoke.ReturnType.IsAssignableFrom(constructType))
- throw new ArgumentOutOfRangeException("delegateType", "delegate return type must be assignable from construction type");
- ParameterInfo[] parameters = invoke.GetParameters();
- Type[] parameterTypes = parameters.Select(p => p.ParameterType).ToArray();
- ConstructorInfo constructor = constructType.GetConstructor(parameterTypes);
- if (constructor == null)
- throw new MissingMethodException(constructType.FullName, "no constructor found matching delegate parameter types");
- // Compile the expression
- ParameterExpression[] parameterExpressions =
- parameters.Select(pi => Expression.Parameter(pi.ParameterType, pi.Name)).ToArray();
- NewExpression newExpression =
- Expression.New(constructor, parameterExpressions.Cast<Expression>().ToArray());
- return Expression.Lambda(delegateType, newExpression, parameterExpressions).Compile();
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement