我假设您实际上想要标题和作者之间的 &&,但是 || 在每个标题/作者组合之间。假设你有这些:
Expression<Func<Post, bool>> where1 = p => p.Title == "title1" && p.Author == "author1";
Expression<Func<Post, bool>> where2 = p => p.Title == "title2" && p.Author == "author2";
如果您创建以下扩展方法:
/// <summary>
/// Combines two lambda expressions into a single expression.
/// In the returned expression, the parameter in the second expression will be replaced
/// with the parameter from the first.
/// </summary>
/// <param name="source">The first expression to combine.</param>
/// <param name="other">The second expression to combine.</param>
/// <param name="combiner">
/// How to combine the expression bodies.
/// Example: <see cref="Expression.Or(System.Linq.Expressions.Expression,System.Linq.Expressions.Expression)"/>
/// </param>
/// <returns></returns>
public static Expression<Func<T1, T2>> Combine<T1, T2>(
this Expression<Func<T1, T2>> source,
Expression<Func<T1, T2>> other,
Func<Expression, Expression, BinaryExpression> combiner)
{
var sourceParam = source.Parameters[0];
var visitor = new ParameterReplacerVisitor(other.Parameters[0], sourceParam);
var visitedOther = visitor.VisitAndConvert(other, "Combine");
Require.That(visitedOther != null, () => "VisitAndConvert failed to return a value.");
var newBody = combiner(source.Body, visitedOther.Body);
return Expression.Lambda<Func<T1, T2>>(newBody, sourceParam);
}
...它使用以下ParameterReplacerVisitor
类:
/// <summary>
/// This class replaces one parameter with another everywhere in a given expression tree.
/// This is handy when you have two lambda expressions that you want to combine into one.
/// </summary>
public class ParameterReplacerVisitor : System.Linq.Expressions.ExpressionVisitor
{
private readonly ParameterExpression _originalParameter;
private readonly ParameterExpression _newParameter;
public ParameterReplacerVisitor(ParameterExpression originalParameter, ParameterExpression newParameter)
{
_originalParameter = originalParameter;
_newParameter = newParameter;
}
protected override Expression VisitParameter(ParameterExpression node)
{
if (node == _originalParameter)
{
node = _newParameter;
}
return base.VisitParameter(node);
}
}
...然后您可以像这样组合这些表达式:
var either = where1.Combine(where2, Expression.Or);
然后你可以说:
var query = db.Posts.Where(either);