using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Text; using System.Threading.Tasks; using HH.WCS.Mobox3.DSZSH.AppStart; using HH.WCS.Mobox3.DSZSH.Consts; using HH.WCS.Mobox3.DSZSH.Models; namespace HH.WCS.Mobox3.DSZSH.Helpers { /// /// ExpressionHelper:表达式工具 /// /// /// 定义了 扩展方法,必须声明为 静态类 /// public static class ExprHelper { /// /// 筛选可用货位:未上锁(无任务锁定)、已启用 /// public static Expression> LocIsFree = l => l.N_LOCK_STATE == LockStateCode.无 && l.S_LOCK_STATE == LockStateName.无 && l.C_ENABLE == "Y"; // 默认都是启用 /// /// 筛选空货位:货位当前容器数量为 0 /// public static Expression> LocIsEmpty = l => l.N_CURRENT_NUM == 0; /// /// 筛选满货位:货位当前容器数量 = 货位容器容量 /// public static Expression> LocIsFull = l => l.N_CURRENT_NUM == l.N_CAPACITY; public static Expression> LocCode(string locCode) => l => l.S_CODE == locCode; /// /// 通过货位所属区域筛选货位 /// /// /// 参数 areaName 请使用 AreaName 中的常量 /// /// 区域名称(不是具体的区域号) /// public static Expression> LocBelongsToArea(string areaName) => l => AppStart.Settings.AreaMap[areaName].Contains(l.S_AREA_CODE); // SqlSugar 可以解析系统方法 Contains 为 IN 表达式 /// /// 筛选货位容器关系:查询某个 货位-容器 关系是否存在 /// /// /// /// public static Expression> LocCntrIsBind(string loc, string cntr) => lc => lc.S_LOC_CODE == loc && lc.S_CNTR_CODE == cntr; #region 拓展方法 /// /// 拓展方法:合并两个表达式 /// /// /// /// /// public static Expression> And(this Expression> expr1, Expression> expr2) { var parameter = expr1.Parameters[0]; // 重用第一个表达式的参数 var visitor = new ReplaceExpressionVisitor(expr2.Parameters[0], parameter); var left = expr1.Body; var right = visitor.Visit(expr2.Body); return Expression.Lambda>( Expression.AndAlso(left, right), parameter); } /// /// 辅助类:替换表达式参数 /// 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); } } /// /// 拓展方法:反转表达式(直接取反) /// /// /// 不推荐使用 | 对返回结果整体取反,简单场景下可以使用 /// /// /// /// static Expression> Not(this Expression> expr) { var parameter = expr.Parameters[0]; var body = Expression.Not(expr.Body); return Expression.Lambda>(body, parameter); } /// /// 拓展方法:反转表达式(针对特定运算符进行反转) /// /// /// 推荐使用 | 对表达式中的每个逻辑运算符取反,复杂场景下更合适,能生成更优化的 SQL /// /// /// /// public static Expression> Negate(this Expression> expr) { var visitor = new NegateExpressionVisitor(); var negatedExpr = (Expression>)visitor.Visit(expr); return negatedExpr; } /// /// 辅助类:反转表达式逻辑运算符 /// class NegateExpressionVisitor : ExpressionVisitor { protected override Expression VisitBinary(BinaryExpression node) { // 反转比较运算符 if (node.NodeType == ExpressionType.Equal) return Expression.NotEqual(node.Left, node.Right); if (node.NodeType == ExpressionType.NotEqual) return Expression.Equal(node.Left, node.Right); if (node.NodeType == ExpressionType.GreaterThan) return Expression.LessThanOrEqual(node.Left, node.Right); if (node.NodeType == ExpressionType.GreaterThanOrEqual) return Expression.LessThan(node.Left, node.Right); if (node.NodeType == ExpressionType.LessThan) return Expression.GreaterThanOrEqual(node.Left, node.Right); if (node.NodeType == ExpressionType.LessThanOrEqual) return Expression.GreaterThan(node.Left, node.Right); // 处理逻辑与/或 if (node.NodeType == ExpressionType.AndAlso) return Expression.OrElse(Visit(node.Left), Visit(node.Right)); if (node.NodeType == ExpressionType.OrElse) return Expression.AndAlso(Visit(node.Left), Visit(node.Right)); return base.VisitBinary(node); } protected override Expression VisitUnary(UnaryExpression node) { // 处理双重否定 if (node.NodeType == ExpressionType.Not) return node.Operand; return base.VisitUnary(node); } } #endregion } }