Mam dwa wyrażenia typu Expression<Func<T, bool>>
i chcę przyjąć OR, AND lub NOT z nich i uzyskać nowe wyrażenie tego samego typu
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
źródło
źródło
Odpowiedzi:
Cóż, możesz użyć
Expression.AndAlso
/OrElse
etc do połączenia wyrażeń logicznych, ale problemem są parametry; pracujesz z tym samymParameterExpression
w expr1 i expr2? Jeśli tak, to łatwiej:Działa to również dobrze, aby negować pojedynczą operację:
W przeciwnym razie, w zależności od dostawcy LINQ, możesz być w stanie połączyć je z
Invoke
:Gdzieś mam kod, który ponownie zapisuje drzewo wyrażeń zastępujące węzły, aby usunąć potrzebę
Invoke
, ale jest dość długi (i nie pamiętam, gdzie go zostawiłem ...)Uogólniona wersja, która wybiera najprostszą trasę:
Począwszy od .NET 4.0 istnieje
ExpressionVisitor
klasa, która pozwala budować wyrażenia bezpieczne dla EF.źródło
ExpressionVisitor
) nie istniał wtedy; Mam podobny przykład dotyczący przepełnienia stosu z podobnej daty, w której ręcznie implementuje on gościa: jest to dużo kodu.Możesz użyć Expression.AndAlso / OrElse, aby połączyć wyrażenia logiczne, ale musisz upewnić się, że ParameterExpressions są takie same.
Miałem problemy z EF i PredicateBuilder, więc stworzyłem własny bez uciekania się do Invoke, którego mógłbym użyć w następujący sposób:
Kod źródłowy mojego PredicateBuilder:
I klasa użyteczności do zastąpienia parametrów w lambda:
źródło
Jeśli dostawca nie obsługuje Invoke i konieczne jest połączenie dwóch wyrażeń, można użyć ExpressionVisitor, aby zastąpić parametr w drugim wyrażeniu parametrem w pierwszym wyrażeniu.
źródło
Nic nowego tutaj, ale połączyłem tę odpowiedź z tą odpowiedzią i nieco ją przeredagowałem, aby nawet ja rozumiałem, co się dzieje:
źródło
Musiałem osiągnąć te same wyniki, ale używając czegoś bardziej ogólnego (ponieważ typ nie był znany). Dzięki odpowiedzi Marca w końcu zrozumiałem, co próbowałem osiągnąć:
źródło
Sugeruję jeszcze jedną poprawę w PredicateBuilder i
ExpressionVisitor
rozwiązaniach. ZadzwoniłemUnifyParametersByName
i można go znaleźć w mojej bibliotece MIT: LinqExprHelper . Pozwala łączyć dowolne wyrażenia lambda. Zwykle zadawane są pytania dotyczące wyrażenia predykatowego, ale ta idea obejmuje również wyrażenia projekcyjne.Poniższy kod wykorzystuje metodę,
ExprAdres
która tworzy skomplikowane sparametryzowane wyrażenie, używając wbudowanej lambda. To skomplikowane wyrażenie jest kodowane tylko raz, a następnie ponownie używane, dziękiLinqExprHelper
mini-bibliotece.A to jest kod budujący podwyrażenie:
To, co próbowałem osiągnąć, to wykonywanie sparametryzowanych zapytań bez potrzeby kopiowania i wklejania oraz możliwość korzystania z wbudowanych lambd, które są tak ładne. Bez tych wszystkich wyrażeń pomocniczych byłbym zmuszony stworzyć całe zapytanie za jednym razem.
źródło
Myślę, że to działa dobrze, prawda?
źródło