trees create c# dynamic c#-4.0 expression-trees

create - lambda c#



C#4 "dinámico" en los árboles de expresión (3)

Intento descubrir cómo juntar todas las piezas, y agradecería una muestra de código fuente concreto para un caso simple para empezar.

Considere el siguiente código de C #:

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

Puedo producir una función equivalente en tiempo de ejecución usando árboles de expresiones de la siguiente manera:

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

Ahora dado el siguiente lambda:

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

¿cómo generaría el equivalente usando árboles de expresión (y, presumiblemente, Expression.Dynamic )?


Muy interesante. Supongo que es imposible por la misma razón por la que no se compila lo siguiente:

Expression<Func<dynamic, dynamic, int>> func = (p1, p2) => p1 + p2;

Es un error de compilación CS1963 (que no parece estar documentado por MS):

error CS1963: un árbol de expresiones puede no contener una operación dinámica


No puede hacer eso porque un árbol de expresiones "Puede no contener una operación dinámica".

Lo siguiente no se compilará, debido a la operación +, por ejemplo, y está intentando construir un árbol de expresiones que viola esa regla:

Expression<Func<dynamic, dynamic, dynamic>> f = (x, y) => x + y;

Si no estuviera haciendo una operación Agregar, podría salirse con la suya.

Consulte Cómo crear una expresión <Func <dynamic, dynamic >> - ¿O es un error? para más información.

Editar:

Esto es lo más cercano que puedo conseguir, al definir mi propio método Add que toma parámetros dinámicos y devuelve un resultado dinámico.

class Program { static void Main(string[] args) { var x = Expression.Parameter(typeof(object), "x"); var y = Expression.Parameter(typeof(object), "y"); Func<dynamic, dynamic, dynamic> f = Expression.Lambda<Func<dynamic, dynamic, dynamic>>( 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; } }


Puede crear un árbol de expresiones que represente una expresión de adición de C # dinámica pasando el CallSiteBinder para una expresión de adición dinámica de C # en Expression.Dynamic. Puede descubrir el código para crear el Binder ejecutando Reflector en la expresión dinámica original. Tu ejemplo sería algo como esto:

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<dynamic, dynamic, dynamic> f = Expression.Lambda<Func<object, object, object>>( Expression.Dynamic(binder, typeof(object), x, y), new[] { x, y } ).Compile();