Добавьте к выражению

Я следовал за этим потоком: текст ссылки

Jason дает пример:

public static Expression AndAlso(this Expression left, Expression right)
{
    return Expression.Lambda(Expression.AndAlso(left, right), left.Parameters);
}

и его использование как таковое:

Expression> clientWhere = c => true;
if (filterByClientFName)
{
    clientWhere = clientWhere.AndAlso(c => c.ClientFName == searchForClientFName);
}
if (filterByClientLName)
{
    clientWhere = clientWhere.AndAlso(c => c.ClientLName == searchForClientLName);
}

У меня есть таблица заказов, и я последовал вышеупомянутому примеру, изменив имена столбцов, и я получаю подобную ошибку, которую имел создатель сообщения

Бинарный оператор AndAlso не определяется для типов 'Система. Func2[Models.Order,System.Boolean]' and 'System.Func2 [Модели. Порядок, Система. Булевская переменная]'.

У кого-либо есть какие-либо мысли о том, что я пропускаю?

ОБНОВЛЕННЫЙ:

Eric, я далее следовал за тем, что пользователь предыдущего сообщения спрашивал, здесь текст ссылки

У пользователя есть это

Expression> clientWhere = c => true;
Expression> orderWhere = o => true;
Expression> productWhere = p => true;

if (filterByClient)
{
    clientWhere = c => c.ClientID == searchForClientID;
}

Теперь, если у него должны были быть различные условия в filterByClient, скажите, что он любой имеет clientid и/или некоторое другое имя столбца, как можно было бы создать clientWhere выражение?

13
задан Community 23 May 2017 в 12:25
поделиться

1 ответ

Вы пытаетесь построить дерево выражений, которое представляет это:

c => true && c.ClientFName == searchForClientFName

Вы фактически строите дерево выражений, которое представляет это:

c => c=> true && c => c.ClientFName == searchForClientFName

, что вообще не имеет смысла.

Теперь вы можете наивно подумать, что это сработает:

public static Expression<TDelegate> AndAlso<TDelegate>(this Expression<TDelegate> left, Expression<TDelegate> right) 
{ 
// NOTICE: Combining BODIES:
    return Expression.Lambda<TDelegate>(Expression.AndAlso(left.Body, right.Body), left.Parameters); 
} 

Это даст в вашем случае нечто, представляющее

c => true && c.ClientFName == searchForClientFName

Что выглядит правильным. Но на самом деле это хрупко. Предположим, у вас есть

... d => d.City == "London" ...
... c => c.ClientName == "Fred Smith" ...

, и вы использовали этот метод для их объединения. Вы получите объект, представляющий

c => d.City == "London" && c.ClientName == "Fred Smith"

Что, черт возьми, там делает?

Кроме того, параметры сопоставляются по идентификатору объекта , а не по имени параметра . Если вы сделаете это

... c => c.City == "London" ...
... c => c.ClientName == "Fred Smith" ...

и объедините их в

c => c.City == "London" && c.ClientName == "Fred Smith"

, вы окажетесь в одной лодке; «c» в «c.City» отличается от c , чем два других.

Что вам действительно нужно сделать, так это создать третий объект параметра, заменить его в телах обеих лямбда-выражений для каждого появления их параметров, а затем построить ] новое дерево лямбда-выражений из полученных замещенных тел.

Вы можете создать механизм подстановки, написав посетителя, который проходит по телу дерева выражения, переписывая его по мере продвижения.

31
ответ дан 1 December 2019 в 17:39
поделиться
Другие вопросы по тегам:

Похожие вопросы: