Expression Tree任意のコンストラクション関数パラメータを作成する方法

6734 ワード

class Cat

    {

        public int Year { get; private set; }

        public string Name { get; private set; }



        public Cat()

        { }



        public Cat(int year, string name)

        {

            this.Year = year;

            this.Name = name;

        }



        public override string ToString()

        {

            return string.Format("Name is {0}, Year is {1}", this.Name, this.Year);

        }



    }



    class Test3

    {

        public static void Main(string[] args)

        {

            Cat obj1 = typeof(Cat).CreateInstance<Cat>();

            Cat obj2 = typeof(Cat).CreateInstance<Cat>(2, "Mi Mi");

            Console.WriteLine(obj1.ToString());

            Console.WriteLine(obj2.ToString());

        }

    }



    /// <summary>

    /// Expression Extension Methods

    /// </summary>

    public static class Helper

    {

        /// <summary>

        /// Create object.

        /// </summary>

        /// <param name="type"></param>

        /// <param name="objects"></param>

        /// <returns></returns>

        public static T CreateInstance<T>(this Type type, params object[] objects)

        {

            Type[] typeArray = objects.Select(obj => obj.GetType()).ToArray();

            Func<object[], object> deleObj = BuildDeletgateObj(type, typeArray);

            return (T)deleObj(objects);

        }



        /// <summary>

        /// Get a delegate object and use it to generate a entity class.

        /// </summary>

        /// <param name="type"></param>

        /// <param name="typeList"></param>

        /// <returns></returns>

        private static Func<object[], object> BuildDeletgateObj(Type type, Type[] typeList)

        {

            ConstructorInfo constructor = type.GetConstructor(typeList);

            ParameterExpression paramExp = Expression.Parameter(typeof(object[]), "args_");

            Expression[] expList = GetExpressionArray(typeList, paramExp);



            NewExpression newExp = Expression.New(constructor, expList);



            Expression<Func<object[], object>> expObj = Expression.Lambda<Func<object[], object>>(newExp, paramExp);

            return expObj.Compile();

        }



        /// <summary>

        /// Get an expression array.

        /// </summary>

        /// <param name="typeList"></param>

        /// <param name="paramExp"></param>

        /// <returns></returns>

        private static Expression[] GetExpressionArray(Type[] typeList, ParameterExpression paramExp)

        {

            List<Expression> expList = new List<Expression>();

            for(int i = 0; i < typeList.Length; i++)

            {

                var paramObj = Expression.ArrayIndex(paramExp, Expression.Constant(i));

                var expObj = Expression.Convert(paramObj, typeList[i]);

                expList.Add(expObj);

            }



            return expList.ToArray();

        }

    }