2012-10-05 13 views
7

Esiste un modo semplice per scoprire se un'espressione contiene un'espressione di parametro che non è ulteriormente incapsulata, ad esempio, in MemberExpression.Scoprire se un'espressione contiene un ParameterExpression "solitario"

Esempio:

x => x.Method() ? x : null < = 1 occorrenza di x senza alcuna ulteriore valutazione

x => x.Method() ? x.Property : null < = 0 occorrenze di x senza alcuna ulteriore valutazione

In poche parole il mio caso d'uso è che so che il Metodo (nessun parametro) e valori di proprietà e vogliono scoprire se questo è sufficiente per valutare l'espressione senza recuperare l'intero "oggetto" dall'archivio.

Modifica: Il mio esempio può essere semplificato. Esistono altri tipi di espressioni che devono essere gestiti (ad esempio UnaryExpression).

x => ((Cast) x).Property < = 0 occorrenze di x senza alcuna ulteriore valutazione

Sto cercando una risposta alla seguente domanda:

dato un'espressione, se conosco tutti i valori di ritorno del metodo e valori di proprietà di il parametro di input ma non il valore del parametro stesso, posso valutare l'espressione?

+0

Quale versione di .NET stai usando? –

+0

È .net 3.5 (ma ho anche una versione .net 4 dove potrei usare questo) – lindstromhenrik

risposta

1

Se si utilizza .NET 4 o versione successiva, è possibile utilizzare ExpressionVisitor per questo.

Io non sono molto sicuro di come si definisce "il parametro solitario", ma se si desidera escludere diretti chiamate di metodo, membro accessi e indicizzatore accede sui parametri, si può usare qualcosa di simile (non testata):

Utilizzare in questo modo:

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

Questo è il mio approccio attuale (ho il mio ExpressionVisitor per 3.5). Tuttavia ci sono più espressioni che devono essere contate e temo che ne manchi qualcuno. Uno è per esempio UnaryExpression: x => ((Cast) x) .Property. – lindstromhenrik

+0

@lindstromhenrik: Credo che dovrai definire "solitario" molto bene, come se lo includessi, è piuttosto vago. – Ani

+0

Ho provato a dare una spiegazione migliore ma non sono ancora sicuro di cosa chiamare il problema ;-) – lindstromhenrik

Problemi correlati