Search code examples
c#expression-treeslinq-expressions

Rewritten expression calls operator method ... but the original node had no operator method


I'm trying to change a part of an expression tree, where a property X of type MyEnum is compared to some value x:

$model.X == .Constant<MyEnum>(x)

I want to modify the tree to substitute the comparison to compare a property Y of type Guid with a value y (which will be derived from x).

$model.Y == .Constant<Guid>(y)

So I've inherited from ExpressionVisitor and I've overridden VisitMember to substitute Y for X, and I've overridden VisitConstant to substitute y for x.

Running this yields the following InvalidOperationException:

System.InvalidOperationException : Rewritten expression calls operator method 'Boolean op_Equality(System.Guid, System.Guid)', but the original node had no operator method. If this is is intentional, override 'VisitBinary' and change it to allow this rewrite.

My main question is: what do I have to do in VisitBinary? And my side question is: why is the exception message telling that the original node had no operator method. I think this is not true. It didn't have op_Equality(System.Guid, System.Guid) for sure but it had the equality operator for the MyEnum type, I assume.


Solution

  • I'm guessing from the name that MyEnum is some sort of Enum type.

    Enum types don't need operator methods, because CIL handles equality comparisons for them directly (the same is also true of the built-in integral, floating-point and boolean types).

    There's no way to change the method through BinaryExression.Update() (which will be called either explicitly in your visitor or implicitly because your visitor has changed one or both of the left and right expressions, and that's the default behaviour in that case) you will have to have VisitBinary() create and return a new BinaryExpression through the appropriate call to Expression.Equal().