Выражения... Что я делаю не так?
Я решил уделить немного времени изучению Expressions. Я пытаюсь выполнить очень простое упражнение, а именно добавить два числа. Я столкнулся с исключением, которое сложно найти.
Вот мой код
Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda = Expression.Lambda<Func<int,int,int>>(addExpr, p1, p2); //<-here
var del = lambda.Compile();
var result = del(2,3); //expect 5
но это вызывает исключение ArgumentException: выражение типа 'System.Func`3[System.Int32,System.Int32,System.Int32]' нельзя использовать для возвращаемого типа 'System.Int32'
по линии, указанной выше. Что я сделал не так?
3 ответа
Вы должны обернуть addExpr
в вызове с использованием параметров выражения
Expression<Func<int,int,int>> addExpr = (x, y) => x + y;
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var invokeExpression=Expression.Invoke(addExpr,p1,p2);
var lambda = Expression.Lambda<Func<int,int,int>>(invokeExpression,p1,p2);
var del = lambda.Compile();
var result=del(2,3);
Вызов - это то, как вы набираете p1 к x и p2 к y, в качестве альтернативы вы можете просто написать выше как
var p1 = Expression.Parameter(typeof(int), "p1");
var p2 = Expression.Parameter(typeof(int), "p2");
var lambda=Expresion.Lambda<Func<int,int,int>>(Expression.Add(p1,p2),p1,p2);
var del = lambda.Compile();
var result=del(2,3);
В противном случае вам нужно захватить тело выражения в лямбду и передать параметры выражения.
var lambda=Expresion.Lambda<Func<int,int,int>>(addExpr.Body,addExpr.Parameters);
Ваш код должен быть:
var lambda = Expression.Lambda<Func<Expression<Func<int, int, int>>, int, int>(addExpr, p1, p2);
Ваш текущий код ожидает int
и ваше прохождение в Expression<Func<int, int, int>>
,
Обновить
На самом деле вышеупомянутое не скомпилируется, вам нужно сделать:
var lambda = Expression.Lambda<Func<int, int, int>>(Expression.Add(p1, p2), p1, p2);
Вы должны разложить addExpr
тело или желательно просто написать это с нуля, т.е. Expression.Add(p1,p2)
вместо addExpr
,