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 {
|
/// <summary>
|
/// ExpressionHelper:表达式工具
|
/// </summary>
|
/// <remarks>
|
/// 定义了 扩展方法,必须声明为 静态类
|
/// </remarks>
|
public static class ExprHelper {
|
/// <summary>
|
/// 筛选可用货位:未上锁(无任务锁定)、已启用
|
/// </summary>
|
public static Expression<Func<TN_Location, bool>> LocIsFree =
|
l => l.N_LOCK_STATE == LockStateCode.无
|
&& l.S_LOCK_STATE == LockStateName.无
|
&& l.C_ENABLE == "Y"; // 默认都是启用
|
|
/// <summary>
|
/// 筛选空货位:货位当前容器数量为 0
|
/// </summary>
|
public static Expression<Func<TN_Location, bool>> LocIsEmpty =
|
l => l.N_CURRENT_NUM == 0;
|
|
/// <summary>
|
/// 筛选满货位:货位当前容器数量 = 货位容器容量
|
/// </summary>
|
public static Expression<Func<TN_Location, bool>> LocIsFull =
|
l => l.N_CURRENT_NUM == l.N_CAPACITY;
|
|
public static Expression<Func<TN_Location, bool>> LocCode(string locCode) =>
|
l => l.S_CODE == locCode;
|
|
/// <summary>
|
/// 通过货位所属区域筛选货位
|
/// </summary>
|
/// <remarks>
|
/// 参数 areaName 请使用 AreaName 中的常量
|
/// </remarks>
|
/// <param name="areaName">区域名称(不是具体的区域号)</param>
|
/// <returns></returns>
|
public static Expression<Func<TN_Location, bool>> LocBelongsToArea(string areaName) =>
|
l => AppStart.Settings.AreaMap[areaName].Contains(l.S_AREA_CODE); // SqlSugar 可以解析系统方法 Contains 为 IN 表达式
|
|
/// <summary>
|
/// 筛选货位容器关系:查询某个 货位-容器 关系是否存在
|
/// </summary>
|
/// <param name="loc"></param>
|
/// <param name="cntr"></param>
|
/// <returns></returns>
|
public static Expression<Func<TN_Loc_Container, bool>> LocCntrIsBind(string loc, string cntr) =>
|
lc => lc.S_LOC_CODE == loc && lc.S_CNTR_CODE == cntr;
|
|
#region 拓展方法
|
|
/// <summary>
|
/// 拓展方法:合并两个表达式
|
/// </summary>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="expr1"></param>
|
/// <param name="expr2"></param>
|
/// <returns></returns>
|
public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
|
Expression<Func<T, bool>> 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<Func<T, bool>>(
|
Expression.AndAlso(left, right),
|
parameter);
|
}
|
|
/// <summary>
|
/// 辅助类:替换表达式参数
|
/// </summary>
|
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);
|
}
|
}
|
|
/// <summary>
|
/// 拓展方法:反转表达式(直接取反)
|
/// </summary>
|
/// <remarks>
|
/// 不推荐使用 | 对返回结果整体取反,简单场景下可以使用
|
/// </remarks>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="expr"></param>
|
/// <returns></returns>
|
static Expression<Func<T, bool>> Not<T>(this Expression<Func<T, bool>> expr) {
|
var parameter = expr.Parameters[0];
|
var body = Expression.Not(expr.Body);
|
|
return Expression.Lambda<Func<T, bool>>(body, parameter);
|
}
|
|
/// <summary>
|
/// 拓展方法:反转表达式(针对特定运算符进行反转)
|
/// </summary>
|
/// <remarks>
|
/// 推荐使用 | 对表达式中的每个逻辑运算符取反,复杂场景下更合适,能生成更优化的 SQL
|
/// </remarks>
|
/// <typeparam name="T"></typeparam>
|
/// <param name="expr"></param>
|
/// <returns></returns>
|
public static Expression<Func<T, bool>> Negate<T>(this Expression<Func<T, bool>> expr) {
|
var visitor = new NegateExpressionVisitor();
|
var negatedExpr = (Expression<Func<T, bool>>)visitor.Visit(expr);
|
return negatedExpr;
|
}
|
|
/// <summary>
|
/// 辅助类:反转表达式逻辑运算符
|
/// </summary>
|
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
|
|
}
|
}
|