Example #1
0
        /// <summary>
        /// 式木が表している具体的な値を返します。
        /// </summary>
        /// <param name="exp">値を指定している式木</param>
        /// <returns>値</returns>
        public static object EvaluateValue(this Expression exp)
        {
            // Boxingを展開
            var expression = exp.CastTo <Expression>();

            if (expression is ConstantExpression)
            {   // 定数:値を返す
                return((expression as ConstantExpression).Value);
            }
            if (expression is NewExpression)
            {   // インスタンス生成:生成されたインスタンスを返す
                var expr       = (expression as NewExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                return(expr.Constructor.Invoke(parameters));
            }
            if (expression is NewArrayExpression)
            {   // 配列生成:生成された配列を返す
                var expr = (expression as NewArrayExpression);
                return(expr.Expressions.Select(EvaluateValue).ToArray());
            }
            if (expression is MethodCallExpression)
            {   // メソッド呼び出し:呼び出し結果を返す
                var expr       = (expression as MethodCallExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                var obj        = (expr.Object == null) ? null : EvaluateValue(expr.Object);
                return(expr.Method.Invoke(obj, parameters));
            }
            if (expression is InvocationExpression)
            {   // ラムダ等の呼び出し:呼び出し結果を返す
                var invocation = (expression as InvocationExpression);
                var parameters = invocation.Arguments.Select(x => Expression.Parameter(x.Type)).ToArray();
                var arguments  = invocation.Arguments.Select(EvaluateValue).ToArray();
                var lambda     = Expression.Lambda(invocation, parameters);
                return(lambda.Compile().DynamicInvoke(arguments));
            }
            if (expression is BinaryExpression && expression.NodeType == ExpressionType.ArrayIndex)
            {   // 配列等のインデクサ:そのインデックスの値を返す
                var expr  = (expression as BinaryExpression);
                var array = (Array)EvaluateValue(expr.Left);
                var index = expr.Right.Type == typeof(int)
                          ? (int)EvaluateValue(expr.Right)
                          : (long)EvaluateValue(expr.Right);
                return(array.GetValue(index));
            }

            // メンバ(フィールドまたはプロパティ):プロパティ/フィールド値を取り出す
            // ※インスタンスメンバならインスタンス値を再帰把握
            var member = (expression as MemberExpression);

            if (member != null)
            {
                if (member.Member.MemberType == MemberTypes.Property)
                {
                    var info = (PropertyInfo)member.Member;
                    return((member.Expression != null)
                        ? MemberAccessor.GetValue(EvaluateValue(member.Expression), info)
                        : MemberAccessor.GetStaticValue(info));
                }
                if (member.Member.MemberType == MemberTypes.Field)
                {
                    var info = (FieldInfo)member.Member;
                    return((member.Expression != null)
                        ? MemberAccessor.GetValue(EvaluateValue(member.Expression), info)
                        : MemberAccessor.GetStaticValue(info));
                }
            }

            // ここまでの処理で値を特定できなかった:実行して値を取り出す
            return(Expression.Lambda(expression).Compile().DynamicInvoke());
        }
        /// <summary>
        /// 式木が表している具体的な値を返します。
        /// </summary>
        /// <param name="expression">値を指定している式木</param>
        /// <returns>値</returns>
        public static object EvaluateValue(this Expression expression)
        {
            if (expression is ConstantExpression)
            {   // 定数:値を返す
                return((expression as ConstantExpression).Value);
            }
            if (expression is NewExpression)
            {   // インスタンス生成:生成されたインスタンスを返す
                var expr       = (expression as NewExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                return(expr.Constructor.Invoke(parameters));
            }
            if (expression is NewArrayExpression)
            {   // 配列生成:生成された配列を返す
                var expr = (expression as NewArrayExpression);
                return(expr.Expressions.Select(EvaluateValue).ToArray());
            }
            if (expression is MethodCallExpression)
            {   // メソッド呼び出し:呼び出し結果を返す
                var expr       = (expression as MethodCallExpression);
                var parameters = expr.Arguments.Select(EvaluateValue).ToArray();
                var obj        = (expr.Object == null) ? null : EvaluateValue(expr.Object);
                return(expr.Method.Invoke(obj, parameters));
            }
            if (expression is InvocationExpression)
            {   // ラムダ等の呼び出し:呼び出し結果を返す
                var invocation = (expression as InvocationExpression);
                var parameters = invocation.Arguments.Select(x => Expression.Parameter(x.Type)).ToArray();
                var arguments  = invocation.Arguments.Select(EvaluateValue).ToArray();
                var lambda     = Expression.Lambda(invocation, parameters);
                return(lambda.Compile().DynamicInvoke(arguments));
            }
            if (expression is BinaryExpression && expression.NodeType == ExpressionType.ArrayIndex)
            {   // 配列等のインデクサ:そのインデックスの値を返す
                var expr  = (expression as BinaryExpression);
                var array = (Array)EvaluateValue(expr.Left);
                var index = expr.Right.Type == typeof(int)
                          ? (int)EvaluateValue(expr.Right)
                          : (long)EvaluateValue(expr.Right);
                return(array.GetValue(index));
            }

            // フィールド/プロパティ:1つづつたどっていく
            var memberInfoList = new List <MemberInfo>();
            var temp           = CastTo <Expression>(expression);

            while (!(temp is ConstantExpression))
            {
                var member = CastTo <MemberExpression>(temp);
                if (member == null)
                {     // フィールドでもプロパティでもない
                    if (expression != temp)
                    { // 再帰
                        return(EvaluateValue(temp));
                    }
                    else
                    {   // 再帰できない:ラムダ実行により値取得
                        var lambda = Expression.Lambda(expression);
                        return(lambda.Compile().DynamicInvoke());
                    }
                }
                if (member.Expression == null)
                {   // static
                    if (member.Member.MemberType == MemberTypes.Property)
                    {
                        var info = (PropertyInfo)member.Member;
                        return(MemberAccessor.GetStaticValue(info));
                    }
                    if (member.Member.MemberType == MemberTypes.Field)
                    {
                        var info = (FieldInfo)member.Member;
                        return(MemberAccessor.GetStaticValue(info));
                    }
                    throw new EvaluateException("can't evaluate:" + member.Member.ToString());
                }
                // instance
                memberInfoList.Add(member.Member);
                temp = CastTo <Expression>(member.Expression);
            }
            var value = ((ConstantExpression)temp).Value;

            for (var i = memberInfoList.Count - 1; i >= 0; i--)
            {
                var mi = memberInfoList[i];
                if (mi is PropertyInfo)
                {
                    value = MemberAccessor.GetValue(value, (mi as PropertyInfo));
                }
                else if (mi is FieldInfo)
                {
                    value = MemberAccessor.GetValue(value, (mi as FieldInfo));
                }
            }
            return(value);
        }