2012-10-05 15 views
7

¿Existe una manera simple de averiguar si una expresión contiene una expresión de parámetros que no está incluida en, por ejemplo, MemberExpression?Averiguar si una expresión contiene un parámetro "solo" ParameterExpression

Ejemplo:

x => x.Method() ? x : null < = 1 ocurrencia de x sin ninguna evaluación adicional

x => x.Method() ? x.Property : null < = 0 ocurrencias de x sin ninguna evaluación adicional

En pocas palabras mi caso de uso es que sé que el Método (sin parámetros) y valores de propiedad y desea averiguar si esto es suficiente para evaluar la expresión sin recuperar todo el "objeto" de la tienda.

Editar: Mi ejemplo es tal vez simplificado. Hay más tipos de expresiones que deben manejarse (por ejemplo, UnaryExpression).

x => ((Cast) x).Property < = 0 ocurrencias de x sin ninguna evaluación adicional

Busco una respuesta a la siguiente pregunta: ¿

dada una expresión, si sé que todos los valores de retorno del método y los valores de propiedad de el parámetro de entrada pero no el valor del parámetro en sí, ¿puedo evaluar la expresión?

+0

¿Qué versión de .NET está usando? –

+0

Es .net 3.5 (pero también tengo una versión .net 4 donde podría usar esto) – lindstromhenrik

Respuesta

1

Si está en .NET 4 o posterior, puede usar ExpressionVisitor para esto.

No estoy muy seguro de cómo se defina "parámetro solo", pero si desea excluir llamadas a métodos directos, miembro de accesos y indexador accesos de parámetros, se puede usar algo como esto (no probado):

utilizar de esta manera:

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

Este es mi enfoque actual (tengo mi propio ExpressionVisitor para 3.5). Sin embargo, hay más expresiones que deben ser contadas y me temo que me falta algo. Uno es, por ejemplo, UnaryExpression: x => ((Cast) x) .Property. – lindstromhenrik

+0

@lindstromhenrik: Supongo que vas a tener que definir "solo" muy bien como si incluyeras eso, es bastante vago. – Ani

+0

He tratado de dar una explicación mejor, pero todavía no estoy seguro de cómo llamar al problema ;-) – lindstromhenrik

Cuestiones relacionadas