Dieser Artikel zeigt, wie zwei C# Ausdrücke vom Typ Expression<Func<bool>>
mit logischen und oder, und nicht von Operatoren kombiniert werden. Direkt ist die direkte Verwendung von Operatoren wie expr1 AND expr2
aufgrund von Parameterfehlanpassungen falsch. Es werden mehrere Ansätze vorgestellt, die jeweils unterschiedliche Szenarien behandeln.
Methode 1: Einfache Kombination (identische Parameter)
Wenn beide Ausdrücke denselben Parameter verwenden, besteht ein einfacher Ansatz darin, Expression.AndAlso
oder Expression.OrElse
direkt auf den Ausdruckskörpern zu verwenden:
var body = Expression.AndAlso(expr1.Body, expr2.Body); var lambda = Expression.Lambda<Func<bool>>(body, expr1.Parameters[0]);
Negation ist ähnlich einfach:
static Expression<Func<bool>> Not<T>(this Expression<Func<bool>> expr) { return Expression.Lambda<Func<bool>>(Expression.Not(expr.Body), expr.Parameters[0]); }
Methode 2: Kombinieren Ausdrücke mit unterschiedlichen Parametern mit Invoke
Wenn Ausdrücke unterschiedliche Parameter haben, kann die Invoke
-Methode verwendet werden, um einen neuen Lambda -Ausdruck mit einem gemeinsamen Parameter zu erstellen:
static Expression<Func<bool>> AndAlso<T>(this Expression<Func<bool>> left, Expression<Func<bool>> right) { var param = Expression.Parameter(typeof(T), "x"); var body = Expression.AndAlso(Expression.Invoke(left, param), Expression.Invoke(right, param)); var lambda = Expression.Lambda<Func<bool>>(body, param); return lambda; }
OrElse
wäre ähnlich und ersetzt AndAlso
durch OrElse
.
Methode 3: Optimierte Kombination (griff identische und verschiedene Parameter)
Diese Methode wählt intelligent den einfacheren Ansatz aus, wenn Parameter gleich sind, ansonsten verwendet Invoke
:
static Expression<Func<bool>> AndAlso<T>(this Expression<Func<bool>> expr1, Expression<Func<bool>> expr2) { ParameterExpression param = expr1.Parameters[0]; if (ReferenceEquals(param, expr2.Parameters[0])) { return Expression.Lambda<Func<bool>>(Expression.AndAlso(expr1.Body, expr2.Body), param); } return Expression.Lambda<Func<bool>>(Expression.AndAlso(expr1.Body, Expression.Invoke(expr2, param)), param); }
Methode 4: EF-Safe Für Entity Framework -Kompatibilität bietet ein
eine robuste Lösung:
ExpressionVisitor
public static Expression<Func<bool>> AndAlso<T>(this Expression<Func<bool>> expr1, Expression<Func<bool>> expr2) { var parameter = Expression.Parameter(typeof(T)); var leftVisitor = new ReplaceExpressionVisitor(expr1.Parameters[0], parameter); var left = leftVisitor.Visit(expr1.Body); var rightVisitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var right = rightVisitor.Visit(expr2.Body); return Expression.Lambda<Func<bool>>(Expression.AndAlso(left, right), parameter); } private class ReplaceExpressionVisitor : ExpressionVisitor { private readonly Expression _oldValue; private readonly Expression _newValue; public ReplaceExpressionVisitor(Expression oldValue, Expression newValue) { _oldValue = oldValue; _newValue = newValue; } public override Expression Visit(Expression node) { if (node == _oldValue) return _newValue; return base.Visit(node); } }
ExpressionVisitor
Das obige ist der detaillierte Inhalt vonWie kann ich zwei Expressionsausdrücke mithilfe und oder nicht Operatoren in C#kombinieren?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!