/// <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); }