2016-04-05 9 views
1

Я пытаюсь изменить часть дерева выражений, где свойство X типа MyEnum сравнивается с некоторым значением х:переписано выражение вызывает метод оператора ... но исходный узел не имеет метода оператора

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

Я хочу изменить дерево, чтобы заменить сравнение, чтобы сравнить свойство Y типа Guid со значением y (которое будет получено из x).

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

Так что я унаследовал от ExpressionVisitor и я переопределен VisitMember заменить Y на X, и я переопределен VisitConstant заменить у на х.

Запуск этого приводит к следующим InvalidOperationException:

System.InvalidOperationException: Переписанное выражение вызывает метод оператора Логическое op_Equality (System.Guid, System.Guid) ', но исходный узел не имел какой-либо метода оператора. Если это намеренно, переопределите «VisitBinary» и измените его, чтобы разрешить эту перезапись.

Мой главный вопрос: что мне делать в VisitBinary? И мой вопрос: почему сообщение об исключении говорит о том, что исходный узел не имеет метода оператора. Я думаю, что это неправда. У него не было op_Equality(System.Guid, System.Guid), но у него был оператор равенства для типа MyEnum.

ответ

3

Я предполагаю от имени, что MyEnum является своего рода Enum типа.

Enum типов не нужны методы оператора, поскольку CIL обрабатывает для них сравнения равенства (то же самое относится и к встроенным интегральным, с плавающей точкой и булевым типам).

Невозможно изменить метод с помощью BinaryExression.Update() (который будет либо явно указан у вашего посетителя, либо неявно, потому что ваш посетитель изменил одно или оба из левого и правого выражений, и в этом случае это поведение по умолчанию). должен будет иметь VisitBinary() создать и вернуть новый BinaryExpression через соответствующий звонок Expression.Equal().

+0

Переопределение VisitBinary - лучший выбор в любом случае, потому что он ставит всю логику в одном месте. Интересно, как должен выглядеть код OPs перед тем, как это сделать, вероятно, запутанным с состоянием экземпляра, которое осуществляется через вызовы VisitC. В VisitBinary он может просто осмотреть двух детей, и если они совпадают, выполните переписывание. +1 – usr

+0

Это очень интересное понимание. Я не знал, что классы Expression уже включают знания «CIL» еще до их компиляции. – Dejan

+0

Его более фабричный метод, который делает это, чем сам экземпляр. Стоит отметить, что если бы вы начали с двоичного выражения с другим операционным методом, обновление все равно потерпело бы неудачу, но с другим исключением, поэтому деталь реализации влияет на характер исключения (что, возможно, еще не идеально), но не так ли. –