Я следовал за этим потоком: текст ссылки
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 не определяется для типов 'Система. Func
2[Models.Order,System.Boolean]' and 'System.Func
2 [Модели. Порядок, Система. Булевская переменная]'.
У кого-либо есть какие-либо мысли о том, что я пропускаю?
ОБНОВЛЕННЫЙ:
Eric, я далее следовал за тем, что пользователь предыдущего сообщения спрашивал, здесь текст ссылки
У пользователя есть это
Expression> clientWhere = c => true;
Expression> orderWhere = o => true;
Expression> productWhere = p => true;
if (filterByClient)
{
clientWhere = c => c.ClientID == searchForClientID;
}
Теперь, если у него должны были быть различные условия в filterByClient
, скажите, что он любой имеет clientid
и/или некоторое другое имя столбца, как можно было бы создать clientWhere
выражение?
Вы пытаетесь построить дерево выражений, которое представляет это:
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 , чем два других.
Что вам действительно нужно сделать, так это создать третий объект параметра, заменить его в телах обеих лямбда-выражений для каждого появления их параметров, а затем построить ] новое дерево лямбда-выражений из полученных замещенных тел.
Вы можете создать механизм подстановки, написав посетителя, который проходит по телу дерева выражения, переписывая его по мере продвижения.