В идеальном мире я лично думаю, что операторы ||
и &&
будут самыми простыми и удобочитаемыми. Однако он не скомпилируется.
оператор '||' нельзя применять к операндам типа 'Expression<Func<YourClass,bool>>
' и 'Expression<Func<YourClass,bool>>
'
Поэтому я использую метод расширения для этого. В вашем примере это будет выглядеть так:
.Where(FindInZip(12345).Or(NameStartsWith("XYZ")).And(PostedOnOrAfter(DateTime.Now))
.
Вместо:
.Where(FindInZip(12345) || NameStartsWith("XYZ") && (PostedOnOrAfter(DateTime.Now))
.
Пример выражения:
private Expression<Func<Post,bool>> PostedOnOrAfter(DateTime cutoffDate)
{
return post => post.PostedOn >= cutoffDate;
};
Метод расширения:
public static class PredicateExtensions
{
/// <summary>
/// Begin an expression chain
/// </summary>
/// <typeparam id="T""></typeparam>
/// <param id="value"">Default return value if the chanin is ended early</param>
/// <returns>A lambda expression stub</returns>
public static Expression<Func<T, bool>> Begin<T>(bool value = false)
{
if (value)
return parameter => true; //value cannot be used in place of true/false
return parameter => false;
}
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> left,
Expression<Func<T, bool>> right)
{
return CombineLambdas(left, right, ExpressionType.AndAlso);
}
public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> left, Expression<Func<T, bool>> right)
{
return CombineLambdas(left, right, ExpressionType.OrElse);
}
#region private
private static Expression<Func<T, bool>> CombineLambdas<T>(this Expression<Func<T, bool>> left,
Expression<Func<T, bool>> right, ExpressionType expressionType)
{
//Remove expressions created with Begin<T>()
if (IsExpressionBodyConstant(left))
return (right);
ParameterExpression p = left.Parameters[0];
SubstituteParameterVisitor visitor = new SubstituteParameterVisitor();
visitor.Sub[right.Parameters[0]] = p;
Expression body = Expression.MakeBinary(expressionType, left.Body, visitor.Visit(right.Body));
return Expression.Lambda<Func<T, bool>>(body, p);
}
private static bool IsExpressionBodyConstant<T>(Expression<Func<T, bool>> left)
{
return left.Body.NodeType == ExpressionType.Constant;
}
internal class SubstituteParameterVisitor : ExpressionVisitor
{
public Dictionary<Expression, Expression> Sub = new Dictionary<Expression, Expression>();
protected override Expression VisitParameter(ParameterExpression node)
{
Expression newValue;
if (Sub.TryGetValue(node, out newValue))
{
return newValue;
}
return node;
}
}
#endregion
}
Действительно хорошая статья о LINQ Queries by Extending Expressions. Также источник метода расширения, который я использую.
https://www.red -gate.com / простой разговор / DotNet / сетчатая рамка / давая чёткость-к-Linq-запросам-по-выдвигая-выражение /