>本文演示了如何使用逻辑和OR,而不是运算符组合两个类型的C#表达式。 由于参数不匹配,直接使用Expression<Func<bool>>
之类的操作员是不正确的。 提出了几种方法,每个方法都解决了不同的方案。expr1 AND expr2
>
方法1:简单组合(相同的参数)>
两种表达式都使用相同的参数,则直接在表达式上使用>或Expression.AndAlso
Expression.OrElse
var body = Expression.AndAlso(expr1.Body, expr2.Body); var lambda = Expression.Lambda<Func<bool>>(body, expr1.Parameters[0]);
static Expression<Func<bool>> Not<T>(this Expression<Func<bool>> expr) { return Expression.Lambda<Func<bool>>(Expression.Not(expr.Body), expr.Parameters[0]); }
Invoke
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
AndAlso
方法3:优化组合(处理相同的和不同的参数)OrElse
如果参数相同,此方法智能选择了更简单的方法,否则使用
Invoke
方法4:使用ExpressionVisitor(.NET 4.0和更高版本)
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); }
对于实体框架兼容性,提供了一个可靠的解决方案:
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); } }
以上是我如何使用C#中的操作员和或者不是运算符组合两个表达式表达式?的详细内容。更多信息请关注PHP中文网其他相关文章!