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();