2011-01-18 12 views
6

consideri la seguente espressione:Euristico per "questo" e chiusure OK? (alberi Expression)

class A { 
    int x; 
    public void Method(int y) { 
     Expression<Func<bool>> expr=() => x == y; 
     //... 

Qui, l'espressione comporta una chiusura creato automaticamente y, e un riferimento a this di tipo A per la (implicito) this.x. Entrambi saranno rappresentati come MemberExpression su un ConstantExpression nell'albero delle espressioni. Data un'espressione come expr o un'espressione più complicata con questo riferimento e/o una chiusura, Voglio identificare che un particolare è in realtà "questo" o una chiusura implicitamente costruita per poter rigenerare C# da un albero di espressioni (ExpressionToCode).

Ho costruito una "soluzione" utilizzando una certa euristica poiché non sembra essere una soluzione perfetta.

  • Chiusure e this in lambda sono sempre in ConstantExpressions.
  • Le chiusure e this non sono mai null.
  • Entrambe sono classi, non tipi di valore: non è possibile acquisire un riferimento a this da una struttura. Questo è abbastanza fortunato, perché dire default(StructType).Method() da this.Method() sarebbe altrimenti impossibile ogni volta this == default(StructType).
  • tipi interni (stringhe, enumerazioni, decimale, tipo, tutte le primitive) sono costanti in realtà vere, non this o una chiusura
  • Chiusure e tipi anonimi Iniziamo con < e è annotato con CompilerGeneratedAttribute
    • nomi di chiusura contengono la stringa DisplayClass, i tipi anonimi contengono AnonymousType
    • I tipi anonimi sono generici, le chiusure non lo sono.
    • Le chiusure sono classi nidificate, i tipi anonimi no.
  • this deve essere un tipo normale: non CompilerGenerated e non inizia con <

Sono le euristiche di cui sopra sufficienti per distinguere tra costanti reali, this, chiusure e tipi anonimi? Cioè ci sono casi in cui queste euristiche falliscono o mi manca? È probabile che si rompa nelle versioni future di .NET?

Edit: ho fatto questa domanda in modo aperto, senza esito; Ho riscritto la domanda per includere ciò che ho scoperto finora. Tutti i suggerimenti molto apprezzato - domani scadenza del Bounty, qualsiasi idea a tutti è il benvenuto ...

+0

Sei sicuro che la tua ipotesi è corretta? Secondo me (non sono un esperto;)), la x nell'espressione potrebbe essere solo un 'riferimento' a un int senza alcuna conoscenza di A (e non c'è modo di trovare un A dall'espressione) – Guillaume86

+0

ok ho sbagliato è possibile con gli alberi di espressione (ed è ovvio ^^) – Guillaume86

+0

Sono sicuro che è possibile avvicinarsi a una risposta. Non sono sicuro che sia possibile - Ho aggiunto le mie attuali idee sull'argomento, che sono necessarie per rilevare e differenziare tra tipi generati dal compilatore, costanti reali e tipi di utenti - e notare che il compilatore genera anche anonimi tipi che non sono per chiusure. –

risposta

2

Ok, riesco a trovare circa l'A Tipo dall'espressione:

class Program 
{ 
    class A 
    { 
     int x; 
     public Expression<Func<bool>> Method(int y) 
     { 
      Expression<Func<bool>> expr =() => x == y; 
      return expr; 
     } 
    } 

    static void Main(string[] args) 
    { 
     var expr = new A().Method(10); 

     dynamic body = expr.Body; 

     A instance = body.Left.Expression.Value; 

     Console.Write(instance.ToString()); 

     Console.ReadKey(); 
    } 
} 

La dinamica è solo per andare veloce.

modifica 2: preso

+0

Quello che stai facendo qui funziona * in questo preciso esempio *, ma non funzionerà in generale. Ho messo in evidenza la parte rilevante della domanda riguardo al fatto che si tratta di un'espressione * arbitraria * e ho aggiunto un chiarimento sul perché e su come questo potrebbe essere ottenuto - grazie per l'attenzione! –

+0

ho paura che quello che vuoi fare è impossibile, dal punto di vista dell'espressione, non c'è differenza tra una chiusura "implicita" e una "esplicita" ... – Guillaume86

+0

Cosa intendi: chiusura esplicita? Le chiusure sono sempre implicite; e AFAIK generano classi con 'DisplayClass' nel nome - almeno questo è parte dell'euristica che sto usando finora. –