How to get all the factors of the expression tree that affect its output

For an arbitrary type expression Expression<Func<int>>, how can I get a list of all objects that could, but not necessarily, influence the result.

I am looking for a function like this:

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

Example 1

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

where aand bare ints, GetFactorsreturns IEnumerable<object>containing aand b.

Example 2

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

GetFactorsreturns IEnumerable<object>containing obj1, obj2, a, b, cand d.

+3
source share
1 answer

You need to implement a custom expression visitor class as follows:

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.

+2

All Articles