3

给定 type 的任意表达式,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;

where aand bare ints,GetFactors将返回一个IEnumerable<object>包含aand b

示例 2

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

GetFactors将返回IEnumerable<object>包含obj1, obj2, a, b, c, 和d.

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 回答