3

タイプの任意の式が与えられた場合Expression<Func<int>>、結果に影響を与える可能性があるが、必ずしもそうとは限らないすべてのオブジェクトのリストを取得するにはどうすればよいですか。

私はこのような関数を探しています:

IEnumerable<object> GetFactors(Expression<Func<int>> expression)
{
    //return a list of all objects in the expression that affect the result.
}

例1

Expression<Func<int>> expression = () => a + b;

ここでa、およびbintsであり、含むおよびGetFactorsを返します。IEnumerable<object>ab

例2

Expression<Func<int>> expression = () => obj1 != obj2 ? a + b : c + d;

GetFactorsIEnumerable<object>含む、、、、、、obj1およびobj2を返します。abcd

4

1 に答える 1

2

次のようなカスタム式ビジタークラスを実装する必要があります。

public class FactorVisitor : ExpressionVisitor
{
    List<object> factors = new List<object>();

    private FactorVisitor(Expression<Func<int>> expression)
    {
        Visit(expression);
    }

    public static List<object> GetFactors(Expression<Func<int>> expression)
    {
        return new FactorVisitor(expression).factors;
    }

    // Add this method for listing compile-time constant values
    protected override Expression VisitConstant(ConstantExpression node)
    {
        factors.Add(node.Value);
        return node;
    }

    protected override Expression VisitMember(MemberExpression node)
    {
        if (CanBeEvaluated(node))
        {
            factors.Add(Evaluate(node));
        }
        return node;
    }

    private static bool CanBeEvaluated(MemberExpression exp)
    {
        while (exp.Expression.NodeType == ExpressionType.MemberAccess)
        {
            exp = (MemberExpression) exp.Expression;
        }

        return (exp.Expression.NodeType == ExpressionType.Constant);
    }

    private static object Evaluate(Expression exp)
    {
        if (exp.NodeType == ExpressionType.Constant)
        {
            return ((ConstantExpression) exp).Value;
        }
        else
        {
            MemberExpression mexp = (MemberExpression) exp;
            object value = Evaluate(mexp.Expression);

            FieldInfo field = mexp.Member as FieldInfo;
            if (field != null)
            {
                return field.GetValue(value);
            }
            else
            {
                PropertyInfo property = (PropertyInfo) mexp.Member;
                return property.GetValue(value, null);
            }
        }
    }
}

のようなメンバー呼び出しの場合でも、変数の値のみを取得することに注意してくださいa.b

于 2012-05-01T14:32:45.180 に答える