C # 4 “dinamico” negli alberi di espressione

Sto cercando di capire come mettere insieme tutti i pezzi e apprezzerei un esempio concreto di codice sorgente per un caso semplice con cui iniziare.

Considera il seguente codice C #:

Func f = (x, y) => x + y; 

Posso produrre una funzione equivalente in fase di esecuzione usando gli alberi di espressione come segue:

 var x = Expression.Parameter(typeof(int), "x"); var y = Expression.Parameter(typeof(int), "y"); Func f = Expression.Lambda<Func>( Expression.Add(x, y), new[] { x, y } ).Compile(); 

Ora dato il seguente lambda:

 Func f = (x, y) => x + y; 

come potrei generare l’equivalente usando gli alberi di espressione (e, presumibilmente, Expression.Dynamic )?

È ansible creare un albero di espressioni che rappresenti un’espressione di aggiunta C # dynamic passando CallSiteBinder per un’espressione di aggiunta C # dynamic in Expression.Dynamic. È ansible scoprire il codice per creare il Raccoglitore eseguendo Reflector sull’espressione dynamic originale. Il tuo esempio andrebbe in questo modo:

 var x = Expression.Parameter(typeof(object), "x"); var y = Expression.Parameter(typeof(object), "y"); var binder = Binder.BinaryOperation( CSharpBinderFlags.None, ExpressionType.Add, typeof(Program), new CSharpArgumentInfo[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null), CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null)}); Func f = Expression.Lambda>( Expression.Dynamic(binder, typeof(object), x, y), new[] { x, y } ).Compile(); 

Non è ansible farlo perché un albero di espressioni “Potrebbe non contenere un’operazione dynamic”.

Quanto segue non verrà compilato, ad esempio, a causa dell’operazione + e si sta tentando di creare un albero di espressioni che violi tale regola:

  Expression> f = (x, y) => x + y; 

Se non stavi facendo un’operazione Aggiungi potresti farla franca.

Vedi Come creare un’espressione > – O è un bug? per maggiori informazioni.

Modificare:

Questo è il più vicino ansible, definendo il mio metodo Add che prende parametri dinamici e restituisce un risultato dinamico.

  class Program { static void Main(string[] args) { var x = Expression.Parameter(typeof(object), "x"); var y = Expression.Parameter(typeof(object), "y"); Func f = Expression.Lambda>( Expression.Call(typeof(Program), "Add", null, x, y), new[] { x, y } ).Compile(); Console.WriteLine(f(5, 2)); Console.ReadKey(); } public static dynamic Add(dynamic x, dynamic y) { return x + y; } } 

Molto interessante. Immagino sia imansible per la stessa ragione che non si compila quanto segue:

 Expression> func = (p1, p2) => p1 + p2; 

Si tratta di un errore del compilatore CS1963 (che non sembra essere documentato dalla MS):

errore CS1963: una struttura di espressioni non può contenere un’operazione dynamic