【问题标题】:Finding out if an Expression contains a "lonely" ParameterExpression找出一个表达式是否包含一个“孤独的”参数表达式
【发布时间】:2012-10-05 22:28:28
【问题描述】:

是否有一种简单的方法可以确定表达式是否包含未进一步包装的 ParameterExpression,例如 MemberExpression。

例子:

x => x.Method() ? x : null

x => x.Method() ? x.Property : null

简单地说,我的用例是我知道方法(无参数)和属性值,并想知道这是否足以在不从存储中获取整个“对象”的情况下评估表达式。

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

x => ((Cast) x).Property

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

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

【问题讨论】:

  • 您使用的是什么版本的 .NET?
  • 它是 .net 3.5(但我也有一个 .net 4 版本,我可以使用它)

标签: c# expression


【解决方案1】:

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

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

像这样使用它:

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

【讨论】:

  • 这是我目前的方法(我有自己的 ExpressionVisitor 3.5)。然而,还有更多的表达式需要计算,恐怕我错过了一些。一个是例如 UnaryExpression: x => ((Cast) x).Property.
  • @lindstromhenrik:我猜你必须很好地定义“孤独”,如果你把它包括在内,它就很模糊了。
  • 我试图给出更好的解释,但我仍然不确定如何称呼这个问题 ;-)
猜你喜欢
  • 1970-01-01
  • 2012-09-01
  • 1970-01-01
  • 2011-04-13
  • 1970-01-01
  • 1970-01-01
  • 2021-10-09
  • 2012-11-26
相关资源
最近更新 更多