Ich habe zwei Typausdrücke Expression<Func<T, bool>>
und möchte zu OR, AND oder NOT von diesen wechseln und einen neuen Ausdruck desselben Typs erhalten
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
quelle
quelle
Antworten:
Nun, Sie können
Expression.AndAlso
/OrElse
etc verwenden, um logische Ausdrücke zu kombinieren, aber das Problem sind die Parameter;ParameterExpression
arbeitest du mit dem gleichen in expr1 und expr2? Wenn ja, ist es einfacher:Dies funktioniert auch gut, um eine einzelne Operation zu negieren:
Andernfalls können Sie sie je nach LINQ-Anbieter möglicherweise kombinieren mit
Invoke
:Irgendwo habe ich Code, der einen Ausdrucksbaum neu schreibt, der Knoten ersetzt, um die Notwendigkeit zu beseitigen
Invoke
, aber er ist ziemlich lang (und ich kann mich nicht erinnern, wo ich ihn gelassen habe ...)Verallgemeinerte Version, die den einfachsten Weg wählt:
Ab .NET 4.0 gibt es die
ExpressionVisitor
Klasse, mit der Sie Ausdrücke erstellen können, die EF-sicher sind.quelle
ExpressionVisitor
) existierte damals noch nicht ; Ich habe ein verwandtes Beispiel für den Stapelüberlauf ab einem ähnlichen Datum, bei dem der Besucher manuell implementiert wird: Es ist viel Code.Sie können Expression.AndAlso / OrElse verwenden, um logische Ausdrücke zu kombinieren. Sie müssen jedoch sicherstellen, dass die ParameterExpressions identisch sind.
Ich hatte Probleme mit EF und dem PredicateBuilder, also habe ich meine eigenen gemacht, ohne auf Invoke zurückzugreifen, die ich so verwenden könnte:
Quellcode für meinen PredicateBuilder:
Und die Utility-Klasse zum Ersetzen der Parameter in einem Lambda:
quelle
Wenn Ihr Provider Invoke nicht unterstützt und Sie zwei Ausdrücke kombinieren müssen, können Sie einen ExpressionVisitor verwenden, um den Parameter im zweiten Ausdruck durch den Parameter im ersten Ausdruck zu ersetzen.
quelle
Nichts Neues hier, aber diese Antwort mit dieser Antwort verheiratet und leicht überarbeitet, so dass selbst ich verstehe, was los ist:
quelle
Ich musste die gleichen Ergebnisse erzielen, aber etwas allgemeineres verwenden (da der Typ nicht bekannt war). Dank Marc's Antwort fand ich endlich heraus, was ich erreichen wollte:
quelle
Ich schlage eine weitere Verbesserung von PredicateBuilder und
ExpressionVisitor
Lösungen vor. Ich habe es angerufenUnifyParametersByName
und Sie finden es in meiner MIT-Bibliothek: LinqExprHelper . Es ermöglicht das Kombinieren von willkürlichen Lambda-Ausdrücken. Normalerweise werden die Fragen zum Prädikatenausdruck gestellt, aber diese Idee erstreckt sich auch auf Projektionsausdrücke.Der folgende Code verwendet eine Methode,
ExprAdres
die mithilfe von Inline-Lambda einen komplizierten parametrisierten Ausdruck erstellt. Dieser komplizierte Ausdruck wird nur einmal codiert und dank derLinqExprHelper
Minibibliothek wiederverwendet .Und dies ist der Code für die Erstellung von Unterausdrücken:
Was ich erreichen wollte, war, parametrisierte Abfragen durchzuführen, ohne kopieren und einfügen zu müssen und mit der Fähigkeit, Inline-Lambdas zu verwenden, die so hübsch sind. Ohne all diese Hilfsmittel wäre ich gezwungen, eine ganze Abfrage auf einmal zu erstellen.
quelle
Ich denke, das funktioniert gut, nicht wahr?
quelle