组合两个表达式(表达式<Func<T,bool>)

组合两个表达式(表达式<Func<T,bool>)

我有两个类型的表达式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


守着星空守着你
浏览 1686回答 3
3回答

墨色风雨

你可以用Expression.AndAlso&nbsp;/&nbsp;OrElse等等来组合逻辑表达式,但问题在于参数;您是否使用相同的ParameterExpression在expr1和expr2中?如果是这样,则更容易:var&nbsp;body&nbsp;=&nbsp;Expression.AndAlso(expr1.Body,&nbsp;expr2.Body);var&nbsp;lambda&nbsp;=&nbsp;Expression.Lambda<Func<T,bool>>(body,&nbsp;expr1.Parameters[0]);这对于否定单个操作也很有效:static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;Not<T>( &nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;expr){ &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.Not(expr.Body),&nbsp;expr.Parameters[0]);}否则,根据LINQ提供程序的不同,您可能可以将它们与Invoke://&nbsp;OrElse&nbsp;is&nbsp;very&nbsp;similar...static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;AndAlso<T>( &nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;left, &nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;right){ &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;param&nbsp;=&nbsp;Expression.Parameter(typeof(T),&nbsp;"x"); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;body&nbsp;=&nbsp;Expression.AndAlso( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.Invoke(left,&nbsp;param), &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.Invoke(right,&nbsp;param) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;); &nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;lambda&nbsp;=&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>(body,&nbsp;param); &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;lambda;}在某个地方,我有一些代码可以重写表达式树,替换节点以消除对Invoke,但它很长(我不记得我把它放在哪里了.)选择最简单路径的通用版本:static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;AndAlso<T>( &nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;expr1, &nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;expr2){ &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;need&nbsp;to&nbsp;detect&nbsp;whether&nbsp;they&nbsp;use&nbsp;the&nbsp;same &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;parameter&nbsp;instance;&nbsp;if&nbsp;not,&nbsp;they&nbsp;need&nbsp;fixing &nbsp;&nbsp;&nbsp;&nbsp;ParameterExpression&nbsp;param&nbsp;=&nbsp;expr1.Parameters[0]; &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(ReferenceEquals(param,&nbsp;expr2.Parameters[0])) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;simple&nbsp;version &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.AndAlso(expr1.Body,&nbsp;expr2.Body),&nbsp;param); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;otherwise,&nbsp;keep&nbsp;expr1&nbsp;"as&nbsp;is"&nbsp;and&nbsp;invoke&nbsp;expr2 &nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.AndAlso( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;expr1.Body, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.Invoke(expr2,&nbsp;param)),&nbsp;param);}从.NET 4.0开始。有ExpressionVistor类,它允许您构建EF安全的表达式。&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;AndAlso<T>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;expr1, &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;expr2) &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;parameter&nbsp;=&nbsp;Expression.Parameter(typeof&nbsp;(T)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;leftVisitor&nbsp;=&nbsp;new&nbsp;ReplaceExpressionVisitor(expr1.Parameters[0],&nbsp;parameter); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;left&nbsp;=&nbsp;leftVisitor.Visit(expr1.Body); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;rightVisitor&nbsp;=&nbsp;new&nbsp;ReplaceExpressionVisitor(expr2.Parameters[0],&nbsp;parameter); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;var&nbsp;right&nbsp;=&nbsp;rightVisitor.Visit(expr2.Body); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>( &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression.AndAlso(left,&nbsp;right),&nbsp;parameter); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;class&nbsp;ReplaceExpressionVisitor &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;:&nbsp;ExpressionVisitor &nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;readonly&nbsp;Expression&nbsp;_oldValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;readonly&nbsp;Expression&nbsp;_newValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ReplaceExpressionVisitor(Expression&nbsp;oldValue,&nbsp;Expression&nbsp;newValue) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_oldValue&nbsp;=&nbsp;oldValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;_newValue&nbsp;=&nbsp;newValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;override&nbsp;Expression&nbsp;Visit(Expression&nbsp;node) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(node&nbsp;==&nbsp;_oldValue) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;_newValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;base.Visit(node); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}

Qyouu

您可以使用Expression.AndAlso/OrElse组合逻辑表达式,但必须确保参数表达式是相同的。我在EF和预测生成器所以我做了自己的事而不诉诸于调用,所以我可以像这样使用:var&nbsp;filterC&nbsp;=&nbsp;filterA.And(filterb);我的预测生成器的源代码:public&nbsp;static&nbsp;class&nbsp;PredicateBuilder&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;And<T>(this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;a,&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;b)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ParameterExpression&nbsp;p&nbsp;=&nbsp;a.Parameters[0]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SubstExpressionVisitor&nbsp;visitor&nbsp;=&nbsp;new&nbsp;SubstExpressionVisitor(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visitor.subst[b.Parameters[0]]&nbsp;=&nbsp;p; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;body&nbsp;=&nbsp;Expression.AndAlso(a.Body,&nbsp;visitor.Visit(b.Body)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>(body,&nbsp;p); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;static&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;Or<T>(this&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;a,&nbsp;Expression<Func<T,&nbsp;bool>>&nbsp;b)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;ParameterExpression&nbsp;p&nbsp;=&nbsp;a.Parameters[0]; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SubstExpressionVisitor&nbsp;visitor&nbsp;=&nbsp;new&nbsp;SubstExpressionVisitor(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;visitor.subst[b.Parameters[0]]&nbsp;=&nbsp;p; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;body&nbsp;=&nbsp;Expression.OrElse(a.Body,&nbsp;visitor.Visit(b.Body)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Expression.Lambda<Func<T,&nbsp;bool>>(body,&nbsp;p); &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;&nbsp;&nbsp;}以及替换lambda中的参数的实用程序类:internal&nbsp;class&nbsp;SubstExpressionVisitor&nbsp;:&nbsp;System.Linq.Expressions.ExpressionVisitor&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;Dictionary<Expression,&nbsp;Expression>&nbsp;subst&nbsp;=&nbsp;new&nbsp;Dictionary<Expression,&nbsp;Expression>(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protected&nbsp;override&nbsp;Expression&nbsp;VisitParameter(ParameterExpression&nbsp;node)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Expression&nbsp;newValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(subst.TryGetValue(node,&nbsp;out&nbsp;newValue))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;newValue; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;node; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;}
打开App,查看更多内容
随时随地看视频慕课网APP