找出一个表达式是否包含一个"孤独的" ParameterExpression

时间:2012-10-05 13:38:55

标签: c# expression

是否有一种简单的方法可以找出Expression是否包含一个没有进一步包含的ParameterExpression,例如MemberExpression。

示例:

x => x.Method() ? x : null< = 1出现x而无需进一步评估

x => x.Method() ? x.Property : null< = 0出现x而无需进一步评估

简单地说,我的用例是我知道方法(没有参数)和属性值,并想知道这是否足以评估表达式而不从商店中获取整个“对象”。

编辑: 我的例子可能是简化。需要处理更多表达式类型(例如,UnaryExpression)。

x => ((Cast) x).Property< = 0出现x而无需进一步评估

我正在寻找以下问题的答案:

给定一个表达式,如果我知道输入参数的所有方法返回值和属性值而不是参数值本身,我可以评估表达式吗?

1 个答案:

答案 0 :(得分:1)

如果您使用的是.NET 4或更高版本,则可以使用ExpressionVisitor

我不太确定你如何定义“孤独参数”,但是如果要排除直接方法调用,成员访问和索引器访问参数,你可以使用这样的东西(未经测试) ):

像这样使用:

new MyExpressionVisitor().GetNumLonelyParameterExpressions(myExpression.Body)

public class MyExpressionVisitor : ExpressionVisitor
{
    private int numLonelyParameterExpressions;

    public int GetNumLonelyParameterExpressions(Expression expression)
    {
        numLonelyParameterExpressions = 0;
        Visit(expression);
        return numLonelyParameterExpressions;
    }

    protected override Expression VisitParameter(ParameterExpression node)
    {
        // Every time we encounter a lonely parameter, increment.
        numLonelyParameterExpressions++;
        return base.VisitParameter(node);
    }

    protected override Expression VisitMethodCall(MethodCallExpression node)
    {
        // Don't visit parameters that have methods called on them.
         var expr = (node.Object is ParameterExpression)
            ? Expression.Default(node.Object.Type)
            : node.Object;

        // We need to make sure the arguments are visited though.
        return base.VisitMethodCall(node.Update(expr, node.Arguments));
    }


    protected override Expression VisitMember(MemberExpression node)
    {
          // Don't visit parameters with member accesses on them.
          if (node.Expression is ParameterExpression)
              return Expression.Default(node.Type);

          return base.VisitMember(node);
    }

    protected override Expression VisitIndex(IndexExpression node)
    {
         // Same idea here.
         var expr = (node.Object is ParameterExpression)
             ? Expression.Default(node.Object.Type)
             : node.Object;

         return base.VisitIndex(node.Update(expr, node.Arguments));
    }
}