I need to use ExpressionVisitor to analyse an Expression before executing it. For my needs, i need to evaluate the right part of a Divide expression but i don't know how to do it. Here's a sample code that i have:
internal class RulesChecker : ExpressionVisitor
{
private readonly object data;
public RulesChecker(object data)
{
this.data = data;
}
protected override Expression VisitBinary(BinaryExpression node)
{
if (node.NodeType == ExpressionType.Divide)
{
var rightExpression = node.Right;
// compile the right expression and get his value
}
return base.VisitBinary(node);
}
}
Suppose that i have this code to evaluate:
Expression<Func<DataInfo, decimal?>> expression = x => x.A / (x.B + x.C);
var rulesChecker = new RulesChecker(data);
rulesChecker.Visit(expression);
In the VisitBinary function, i will receive a node that will contain the left and right part of the divide operation. My question is, how can i evaluate the value that i will get in the right part of the operation?
I think the hardest part of this problem is dealing with the variables. So I would start by replacing the variables for constants. After that you just need to execute and update the Expression.
Usually you could use this method to evaluate a lambda expression (and pass ):
However, in your case this won't work, because the expression you're trying to evaluate depends on
x
, which cannot be evaluated, unless you specify a concrete value for it, as Wiktor suggested.In order to specify a value for the parameter, you need to modify the method as such:
This version of the method, however, must take as a parameter the ExpressionParameter object that represents the
x
in your expression in order for it to know what to do with the value passed toDynamicInvoke()
.In order to obtain the appropriate
ExpressionParameter
object you need access to the root expression, not to one of its nodes, so I guess it would be awkward to do it in a visitor.If I understand you correctly, you want to return the result of visiting your expression to be a modified expression tree that has the right-hand sides of divisions evaluated in some way. You would use the
Update
method of theBinaryExpression
to replace the right node with your value:In this code,
newRightExpression
needs to be of a type that inherits fromExpression
. If the right node evaluates to, say, adouble
value, then you would need to wrap it in aConstantExpression
:I think @w0lf is on the correct path.
To get the parameters from within the visitor, you need to override VisitLambda. Best way to do it is to override every available method of the visitor, and pass the parameters to all of your methods.
Another method is to save the latest parameters. Actually, parameters array will be the same throughout a whole lambda expression.
Here is a piece of code, multiplying the right side of a division operation by two and replacing it in the original expression, assuming right side and left side are of type double.