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
}
}