kazelee
2025-05-09 62e3ff7506396fcb7f7737900806e838c2466aa3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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
 
    }
}