У меня есть два выражения типа, Expression<Func<T, bool>>
и я хочу взять из ИЛИ, И или НЕ из них и получить новое выражение того же типа
Expression<Func<T, bool>> expr1;
Expression<Func<T, bool>> expr2;
...
//how to do this (the code below will obviously not work)
Expression<Func<T, bool>> andExpression = expr AND expr2
c#
linq
lambda
expression
BjartN
источник
источник
Ответы:
Ну, вы можете использовать
Expression.AndAlso
/OrElse
etc для объединения логических выражений, но проблема в параметрах; вы работаете с тем жеParameterExpression
в expr1 и expr2? Если так, то это проще:Это также хорошо работает, чтобы отменить одну операцию:
В противном случае, в зависимости от поставщика LINQ, вы можете комбинировать их с
Invoke
:Где-то у меня есть некоторый код, который переписывает дерево выражений, заменяющее узлы, чтобы избавить от необходимости
Invoke
, но это довольно долго (и я не могу вспомнить, где я его оставил ...)Обобщенная версия, которая выбирает самый простой маршрут:
Начиная с .NET 4.0, существует
ExpressionVisitor
класс, который позволяет создавать выражения, безопасные для EF.источник
ExpressionVisitor
) тогда еще не существовал ; У меня есть похожий пример на stackoverflow с аналогичной даты, когда он реализует посетителя вручную: это много кода.Вы можете использовать Expression.AndAlso / OrElse для объединения логических выражений, но вы должны убедиться, что ParameterExpressions одинаковы.
У меня были проблемы с EF и PredicateBuilder, поэтому я сделал свой собственный, не прибегая к Invoke, который я мог бы использовать так:
Исходный код для моего PredicateBuilder:
И служебный класс для подстановки параметров в лямбду:
источник
Если ваш провайдер не поддерживает Invoke и вам нужно объединить два выражения, вы можете использовать ExpressionVisitor, чтобы заменить параметр во втором выражении на параметр в первом выражении.
источник
Ничего нового здесь, кроме этого ответа на этот ответ, я немного перефразировал его, чтобы даже я понял, что происходит:
источник
Мне нужно было достичь тех же результатов, но с использованием чего-то более общего (так как тип не был известен). Благодаря ответу Марка я наконец понял, чего я пытался достичь:
источник
Я предлагаю еще одно улучшение для PredicateBuilder и его
ExpressionVisitor
решений. Я назвал это,UnifyParametersByName
и вы можете найти это в моей библиотеке MIT: LinqExprHelper . Это позволяет комбинировать произвольные лямбда-выражения. Обычно задаются вопросы о выражении предиката, но эта идея распространяется и на проекционные выражения.В следующем коде используется метод,
ExprAdres
который создает сложное параметризованное выражение, используя встроенную лямбду. Это сложное выражение кодируется только один раз, а затем используется повторно благодаряLinqExprHelper
мини-библиотеке.И это строительный код подвыражения:
То, чего я пытался добиться, - это выполнять параметризованные запросы без необходимости копирования-вставки и с возможностью использовать встроенные лямбды, которые так хороши. Без всего этого вспомогательного выражения я был бы вынужден создать целый запрос за один раз.
источник
Я думаю, что это прекрасно работает, не так ли?
источник