Search code examples
c#expression-trees

Add expression with BinaryExpression as parameter


How can I perform nested addition operations using Expression? Expression.Lambda<> expected parameters to be of type ParameterExpression, but one of my parameters is a result of addition so its type is BinaryExpression. They don't derive from each other so I cannot cast them and I cannot find any way to convert from BinaryExpression to ParameterExpression.

Example:

var left = Expression.Parameter(typeof(int));
var rightLeft = Expression.Parameter(typeof(int));
var rightRight = Expression.Parameter(typeof(int));
var right = Expression.Multiply(rightLeft, rightRight);

var add = Expression.Add(left, right);

var multiplyResult = Expression.Lambda<Func<int, int, int>>(right, rightLeft, rightRight).Compile()(5, 3);
var result = Expression.Lambda<Func<int, int, int>>(add, left, Expression.Parameter(typeof(int))).Compile();

Last line throws

System.InvalidOperationException: 'variable '' of type 'System.Int32' referenced from scope '', but it is not defined'

Expression should compile to:

var result = left + (rightLeft * rightRight);

Solution

  • You can call Compile just once and refer result of multiplication in other binary expression. Try this code:

    var inputType = typeof(int);
    
    var left = Expression.Parameter(inputType, "left");
    var rightLeft = Expression.Parameter(inputType, "rightLeft");
    var rightRight = Expression.Parameter(inputType, "rightRight");
    
    var multiply = Expression.Multiply(rightLeft, rightRight);
    var add = Expression.Add(left, multiply);
    
    var lambda = Expression.Lambda<Func<int, int, int, int>>(add, left, rightLeft, rightRight);
    Console.WriteLine(lambda.ToString()); // will print "(left, rightLeft, rightRight) => (left + (rightLeft * rightRight))"
    
    var result = lambda.Compile().Invoke(1, 2, 3);
    
    Console.WriteLine(result); // will print "7"