using System; using System.Collections.Generic; using System.Linq.Expressions; namespace Masuit.Tools.Linq { /// /// LINQ扩展方法 /// public static class LinqExtension { /// /// 与连接 /// /// 类型 /// 左条件 /// 右条件 /// 新表达式 public static Expression> And(this Expression> left, Expression> right) { return CombineLambdas(left, right, ExpressionType.AndAlso); } /// /// 与连接 /// /// 类型 /// 左条件 /// 符合什么条件 /// 右条件 /// 新表达式 public static Expression> AndIf(this Expression> left, bool condition, Expression> right) { return condition ? CombineLambdas(left, right, ExpressionType.AndAlso) : left; } /// /// 与连接 /// /// 类型 /// 左条件 /// 符合什么条件 /// 右条件 /// 新表达式 public static Expression> AndIf(this Expression> left, Func condition, Expression> right) { return condition() ? CombineLambdas(left, right, ExpressionType.AndAlso) : left; } /// /// 或连接 /// /// 类型 /// 左条件 /// 右条件 /// 新表达式 public static Expression> Or(this Expression> left, Expression> right) { return CombineLambdas(left, right, ExpressionType.OrElse); } /// /// 或连接 /// /// 类型 /// 左条件 /// 符合什么条件 /// 右条件 /// 新表达式 public static Expression> OrIf(this Expression> left, bool condition, Expression> right) { return condition ? CombineLambdas(left, right, ExpressionType.OrElse) : left; } /// /// 或连接 /// /// 类型 /// 左条件 /// 符合什么条件 /// 右条件 /// 新表达式 public static Expression> OrIf(this Expression> left, Func condition, Expression> right) { return condition() ? CombineLambdas(left, right, ExpressionType.OrElse) : left; } private static Expression> CombineLambdas(this Expression> left, Expression> right, ExpressionType expressionType) { var visitor = new SubstituteParameterVisitor { Sub = { [right.Parameters[0]] = left.Parameters[0] } }; Expression body = Expression.MakeBinary(expressionType, left.Body, visitor.Visit(right.Body)); return Expression.Lambda>(body, left.Parameters[0]); } } internal class SubstituteParameterVisitor : ExpressionVisitor { public Dictionary Sub = new Dictionary(); protected override Expression VisitParameter(ParameterExpression node) { return Sub.TryGetValue(node, out var newValue) ? newValue : node; } } }