c# - ExpressionVisitor и сокрашенные BinaryExpression


1

Привет, Пишу свой linq-провайдер для одной CMS. с помощью ExpressionVisitor пытаюсь разобрать дерево выражений, и в зависимости от встречаемых выражений что-то делать. Проблема возникла вот с этим. Представим, есть 5 примеров (они сами по себе бесмысленны, даны чисто для понимания проблемы):

1. x=> x.IsBool == true
2. x=> x.IsBool != true
3. x=> x.IsBool
4. x=> !x.IsBool
5. x=> x.IsBool && x.IsBool == true

Задача: нужно каждое BinaryExpression превратить в IsBool = 1/0 (как EntityFramework это делает).

Случаи 1 и 2 разбираются легко. Но как быть с теми случаями, где часть выражения упрощена (redundant boolean expression)? Случай 3 просто идет как MemberExpression. Случай 4 аналогично, разве что обернут в UnaryExpression (здесь можно извернуться условием, что это UnaryExpression,который содержит MemberExpression - тогда определяем наше равенство).

Случай 5 - самый мне непонятный. Визитор посетит 2 раза MemberExpression (левую часть x.IsBool, и правую часть от BinaryExpression x.IsBool == true). В таком случае, если просто определять MemberExpression по типу значения boolean, то на выходе я получу что-то типа

IsBool = 1 AND IsBool = 1 = 1

То есть в одной итерации я определяю по нормальному пути, что правая часть это BinaryExpression,а потом еще и в MemberExpression определяю по типу bool и довывожу ненужное.

Я надеюсь развернуто объяснил суть проблемы. Надеюсь, что не очень запутанно :). Буду признателен за помощь.

Источник
  •  44
  •  0
  • 13 янв 2016 2016-01-13 06:44:03
Ну, сделайте несколько проходов. Один проход — заменяете унарные булевы выражения, не являющиеся частью сравнения, на бинарные. Передавайте в сравнение флаг, что сравнение предыдущего уровня — бинарное, например. И сделайте то же для MemberExpression, понятно, не только для унарного. Или что-нибудь похитрее. — 13 янв 20162016-01-13 08:15:10.000000
еще хочу добавить, что ExpressionVisitor палит унарное выражение только в случае 4. В случаях 3 и 5 он не видит его (как положительное унарное выражение). В случае 3 он просто воспринимает его как MemberExpression. Случай 5 - Member And Binary(Member equals Constant). Отсюда и проблемная конверсия IsBool = 1 AND IsBool = 1 =1 — 13 янв 20162016-01-13 07:27:26.000000
Влад, так в том то и пробелма - как определить, что (возьмем случай 5), в первый раз посещая MemberExpression , нам попадается укороченный товарищ, а во втором посещении правого - у нас вполне себе полное сравнение? Визитор же посещает все члены выражения. Я могу определить естественно это, но во втором случае, где выражение полное - я допишу избыточную часть, так как член пришел из BinaryExpression — 13 янв 20162016-01-13 07:14:40.000000
Для случая 5, тем же способом превращаете в x.IsBool == true && x.IsBool == true, и пробегаетесь упростителем выражений: E && E -> E. — 13 янв 20162016-01-13 06:58:28.000000
Случай унарного выражения несложен: проверяйте тип (bool) и дописывайте неявно == true. — 13 янв 20162016-01-13 06:52:53.000000

Ответов пока нет