Example #1
0
        /// <summary>
        ///     This generates a Delegate for a constructor that is strongly typed to the constructor type itself
        ///     It does this by dynamically creating a call via reflection to a constructor and then casting that to the type
        ///     created.
        /// </summary>
        /// <param name="ctorInfo">the constructor info for a constructor.</param>
        /// <returns>A strongly typed delegate for creating new objects of a given type</returns>
        public static Delegate CreateDelegateForConstructor(ConstructorInfo ctorInfo)
        {
            if (ctorInfo == null || ctorInfo.DeclaringType == null)
            {
                throw new ArgumentNullException(nameof(ctorInfo));
            }

            // Get the parameter types for the constructor
            var parameterTypes = ctorInfo.ParameterTypes();

            // Create a set of parameters for the expression
            Expression[] pars = parameterTypes.Select(Expression.Parameter).ToArray();

            // create the call to the constructor 
            Expression expression = Expression.Call(Expression.Constant(ctorInfo),
                typeof(ConstructorInfo).GetMethod("Invoke", new[] {typeof(object[])}),
                Expression.NewArrayInit(typeof(object), pars.Select(each => Expression.TypeAs(each, typeof(object)))));

            // wrap the return type to return the actual declaring type.
            expression = Expression.TypeAs(expression, ctorInfo.DeclaringType);

            // create a Func<...> delegate type for the lambda that we actually want to create
            var funcType = Expression.GetFuncType(parameterTypes.ConcatSingleItem(ctorInfo.DeclaringType).ToArray());

            // dynamically call Lambda<Func<...>> to create a type specific lambda expression 
            //Expression.Lambda<Func<object>>()
            var lambda = (LambdaExpression)LambdaMethodInfo.MakeGenericMethod(funcType).Invoke(null, new object[] {expression, pars});

            // return the compiled lambda
            return lambda.Compile();
        }