Example #1
0
        /// <summary>
        /// 指定された式から値を抽出します。
        /// </summary>
        /// <param name="expression">対象となる式</param>
        /// <returns>値</returns>
        /// <remarks>右辺専用</remarks>
        private object ExtractValue(Expression expression)
        {
            //--- 定数
            if (expression is ConstantExpression)
            {
                return(((ConstantExpression)expression).Value);
            }

            //--- インスタンス生成
            if (expression is NewExpression)
            {
                var expr       = (NewExpression)expression;
                var parameters = expr.Arguments.Select(this.ExtractValue).ToArray();
                return(expr.Constructor.Invoke(parameters));
            }

            //--- 配列生成
            if (expression is NewArrayExpression)
            {
                var expr = (NewArrayExpression)expression;
                return(expr.Expressions.Select(this.ExtractValue).ToArray());
            }

            //--- メソッド呼び出し
            if (expression is MethodCallExpression)
            {
                var expr       = (MethodCallExpression)expression;
                var parameters = expr.Arguments.Select(this.ExtractValue).ToArray();
                var obj        = expr.Object == null
                        ? null                              //--- static
                        : this.ExtractValue(expr.Object);   //--- instance
                return(expr.Method.Invoke(obj, parameters));
            }

            //--- デリゲート/ラムダ式の呼び出し
            if (expression is InvocationExpression)
            {
                var invocation = (InvocationExpression)expression;
                var parameters = invocation.Arguments.Select(x => Expression.Parameter(x.Type)).ToArray();
                var arguments  = invocation.Arguments.Select(this.ExtractValue).ToArray();
                var lambda     = Expression.Lambda(invocation, parameters);
                var result     = lambda.Compile().DynamicInvoke(arguments);
                return(result);
            }

            //--- インデクサ
            if (expression is BinaryExpression)
            {
                if (expression.NodeType == ExpressionType.ArrayIndex)
                {
                    var expr  = (BinaryExpression)expression;
                    var array = (Array)this.ExtractValue(expr.Left);
                    var index = expr.Right.Type == typeof(int)
                          ? (int)this.ExtractValue(expr.Right)
                          : (long)this.ExtractValue(expr.Right);
                    return(array.GetValue(index));
                }
            }

            //--- フィールド / プロパティ
            var memberNames = new List <string>();
            var temp        = expression;

            while (!(temp is ConstantExpression))
            {
                //--- cast
                if (temp is UnaryExpression)
                {
                    if (temp.NodeType == ExpressionType.Convert)
                    {
                        temp = ((UnaryExpression)temp).Operand;
                        continue;
                    }
                }

                //--- not member
                var member = temp as MemberExpression;
                if (member == null)
                {
                    return(this.ExtractValue(temp));
                }

                //--- static
                if (member.Expression == null)
                {
                    if (member.Member.MemberType == MemberTypes.Property)
                    {
                        var info = (PropertyInfo)member.Member;
                        return(info.GetValue(null));
                    }
                    if (member.Member.MemberType == MemberTypes.Field)
                    {
                        var info = (FieldInfo)member.Member;
                        return(info.GetValue(null));
                    }
                    throw new InvalidOperationException("Not field or property.");
                }

                //--- instance
                memberNames.Add(member.Member.Name);
                temp = member.Expression;
            }

            var value = ((ConstantExpression)temp).Value;

            for (int i = memberNames.Count - 1; 0 <= i; i--)
            {
                var getter = AccessorCache.LookupGet(value.GetType(), memberNames[i]);
                value = getter(value);
            }
            return(value);
        }