首页 > 其他分享 >依据前端返回参数,动态构建lambda表达式

依据前端返回参数,动态构建lambda表达式

时间:2022-11-21 23:33:51浏览次数:47  
标签:right 前端 typeof new lambda Expression public 表达式 left

1、构建前端返回类

/// <summary>
    /// 查询明细
    /// </summary>
    public class QueryItem
    {
        /// <summary>
        /// 查询项字段
        /// </summary>
        public String WhereName { get; set; }
        /// <summary>
        /// 查询项方法
        /// </summary>
        public Comparison Method { get; set; }
        /// <summary>
        /// 值
        /// </summary>
        public object Value { get; set; }

        /// <summary>
        /// 连接标识 and 或者 or 检查上一位和下一位是否相同
        /// </summary>
        public string LinkName { get; set; }
        public QueryItem()
        {

        }
        /// <summary>
        /// 有参构造函数
        /// </summary>
        public QueryItem(String whereName, Comparison method, Object value, string linkName)
        {
            WhereName = whereName;
            Method = method;
            Value = value;
            LinkName = linkName;
        }
    }
View Code

2、构建等式运算符

    public enum Comparison
    {
        Equal = 0,
        NoEqual = 1,
        GreaterThan = 2,
        GreaterThanOrEqual = 3,
        LessThan = 4,
        LessThanOrEqual = 5,
        Like = 6,
        LikeLeft = 7,
        LikeRight = 8,
        In = 9,
    }
View Code

3、构建表达式分组类

 public class GroupQuery
    {
        public string LinkName { get; set; }

        public int Count { get; set; }

        public List<QueryItem> Entitys { get; set; }
    }
View Code

4、构建表达式运算符

public enum JoinType
    {
        AndAlso,
        OrElse,
    }
View Code

5、表达式组装方法

public static Expression<Func<T, bool>> BuildExpression<T>
            (List<QueryItem> queryItems)
        {
            if (queryItems == null || queryItems.Count == 0)
                throw new Exception("查询条件不可为空值!");
            // 声明参数
            ParameterExpression exp = Expression.Parameter(typeof(T), "t");
            // 进行分组排序
            var groupList = queryItems.GroupBy(t => t.LinkName)
                .Select(t => new GroupQuery{ LinkName = t.Key, Count = t.Count(), Entitys = t.ToList() })
                .OrderBy(m => m.Count).ToList();

            // 表达式数据集合  采用数据栈 先进先出的原则
            List<Expression?> expressions = new List<Expression?>(); 
            for (int i = groupList.Count - 1; i >= 0; i--)
            {
                var list = groupList[i];
                Expression? expression = GetExpressionNode<T>(list.Entitys, exp, list.Count > 1 ? JoinType.OrElse : JoinType.AndAlso);
                expressions.Add(expression);
            }

            Expression body = GetExpression(expressions);

            return Expression.Lambda<Func<T, bool>>(body, exp);
        }

        /// <summary>
        /// 组装表达式
        /// </summary>
        private static Expression GetExpression(List<Expression> expressions)
        {
            Expression exp = null;

            #region 第一步  获取右侧节点
            Expression right = expressions.First();
            #endregion

            #region 第二步  移除右侧节点 判断剩下的节点
            expressions.Remove(right);
            if(expressions.Count == 0)
            {
                return right;
            }else if(expressions.Count == 1)
            {
                exp = Expression.AndAlso(expressions[0],right);
            }
            else
            {
                Expression left = GetExpression(expressions);
                exp = Expression.AndAlso(left,right);
            }
            #endregion

            return exp;
        }

        /// <summary>
        /// 组装二叉树节点
        /// </summary>
        private static Expression? GetExpressionNode<T>(List<QueryItem> QueryItems,ParameterExpression exp, JoinType joinType)
        {
            Expression expression = null;
            var Querys = QueryItems;
            var last = Querys.Last();

            #region 第一步  取出最后一条作为右侧节点
            // 组装等式左侧
            Expression Node_right_left = Expression.Property(exp, typeof(T).GetProperty(last.WhereName));
            // 组装等式右侧
            Expression Node_right_right = GetExpressionValue(Node_right_left, last.Value);
            // 等式组装完毕
            Expression Node_right_Binary = GetBinaryExpression(Node_right_left, Node_right_right, last.Method);
            #endregion

            #region 第二步  移除最后一条 判断剩余的
            Querys.Remove(last);
            Expression Node_left_Binary = null;
           // 没有左侧节点
            if(Querys.Count == 0)
            {
                return Node_right_Binary;
            }
            // 此时只有一条  代表不用递归了 左侧节点就是当前数据
            else if (Querys.Count == 1)
            {
                var first = Querys.First();

                // 组装等式左侧
                Expression Node_left_left = Expression.Property(exp, typeof(T).GetProperty(first.WhereName));
                // 组装等式右侧
                Expression Node_left_right = GetExpressionValue(Node_left_left, first.Value);
                // 等式组装完毕
                Node_left_Binary = GetBinaryExpression(Node_left_left, Node_left_right, first.Method);
            }
            else
            {
                Node_left_Binary = GetExpressionNode<T>(Querys, exp, joinType);
            }

            #endregion

            #region 第三步  组装二叉树两侧节点
            if (joinType == JoinType.AndAlso)
            {
                expression = Expression.AndAlso(Node_left_Binary, Node_right_Binary);
            }
            else
            {
                expression = Expression.OrElse(Node_left_Binary, Node_right_Binary);
            }
            #endregion

            return expression;
        }

        /// <summary>
        /// 组装等式
        /// </summary>
        private static Expression GetBinaryExpression(Expression left,Expression right, Comparison comparison)
        {
            return comparison switch
            {
                Comparison.Equal => Expression.Equal(left,right),
                Comparison.NoEqual => Expression.NotEqual(left,right),
                Comparison.GreaterThan => Expression.GreaterThan(left,right),
                Comparison.GreaterThanOrEqual => Expression.GreaterThanOrEqual(left,right),
                Comparison.LessThan => Expression.LessThan(left,right),
                Comparison.LessThanOrEqual => Expression.LessThanOrEqual(left,right),
                Comparison.In => Expression.Call(left, typeof(String).GetMethod("Contains", new Type[] { typeof(String) }), right),
                Comparison.Like => Expression.Call(left, typeof(String).GetMethod("Contains", new Type[] { typeof(String) }), right),
                Comparison.LikeLeft => Expression.Call(left, typeof(String).GetMethod("EndsWith", new Type[] { typeof(String) }), right),
                Comparison.LikeRight => Expression.Call(left, typeof(String).GetMethod("StartsWith", new Type[] { typeof(String) }), right),
                _ => throw new Exception ("暂未支持")
            };
        }

        /// <summary>
        /// 获取等式右侧的表达式
        /// </summary>
        private static Expression GetExpressionValue(Expression left,object value)
        {
            Expression right = null;

            #region 处理日期时间

            if (left.Type.Equals(typeof(DateTime)))
            {
                right = Expression.Constant(DateTime.Parse(value.ToString()), typeof(DateTime));
            }
            else if (left.Type.Equals(typeof(Nullable<DateTime>)))
            {
                right = Expression.Constant(DateTime.Parse(value.ToString()), typeof(DateTime?));
            }

            #endregion

            #region 处理Guid

            else if (left.Type.Equals(typeof(Guid)))
            {
                right = Expression.Constant(Guid.Parse(value.ToString()), typeof(Guid));
            }
            else if (left.Type.Equals(typeof(Guid?)))
            {
                right = Expression.Constant(Guid.Parse(value.ToString()), typeof(Guid?));
            }

            #endregion

            #region 处理float

            else if (left.Type.Equals(typeof(float)))
            {
                right = Expression.Constant(float.Parse(value.ToString()), typeof(float));
            }
            else if (left.Type.Equals(typeof(float?)))
            {
                right = Expression.Constant(float.Parse(value.ToString()), typeof(float?));
            }

            #endregion

            #region 处理Double

            else if (left.Type.Equals(typeof(double)))
            {
                right = Expression.Constant(double.Parse(value.ToString()), typeof(double));
            }
            else if (left.Type.Equals(typeof(double?)))
            {
                right = Expression.Constant(double.Parse(value.ToString()), typeof(double?));
            }

            #endregion

            #region 处理int

            else if (left.Type.Equals(typeof(int)))
            {
                right = Expression.Constant(int.Parse(value.ToString()), typeof(int));
            }
            else if (left.Type.Equals(typeof(int?)))
            {
                right = Expression.Constant(int.Parse(value.ToString()), typeof(int?));
            }

            #endregion

            #region 处理字符串

            else
            {
                right = Expression.Constant(value.ToString(), typeof(String));
            }

            #endregion

            return right;
        }
View Code

6、构建测试数据

 public class Book
    {
        public int ID { get; set; }

        public string Name { get; set; }

        public string Sex { get; set; }

        public double Money { get; set; }

        public static List<Book> GetBooks() {

            return new List<Book> {
                new Book { ID = 50 ,Name = "张三", Sex = "男",Money = 600 },
                new Book { ID = 150 ,Name = "李四", Sex = "男",Money = 1200 },
                new Book { ID = 100 ,Name = "王五", Sex = "女",Money = 200 },
                new Book { ID = 10 ,Name = "马六", Sex = "女",Money = 8000 },
                new Book { ID = 99 ,Name = "小明", Sex = "女",Money = 1 },
            };
        }
    }
View Code

7、组建前端返回查询明细集合

List<QueryItem> queryItems = new List<QueryItem>();

queryItems.Add(new QueryItem { WhereName = "ID",Method = Comparison.GreaterThan, Value = 0 , LinkName = "ID1" });
queryItems.Add(new QueryItem { WhereName = "ID", Method = Comparison.LessThanOrEqual,Value = 50, LinkName = "ID2" });
queryItems.Add(new QueryItem { WhereName = "Sex", Method = Comparison.Equal, Value = "男", LinkName = "ID" });
queryItems.Add(new QueryItem { WhereName = "Money", Method = Comparison.GreaterThan, Value = 100, LinkName = "ID" });
queryItems.Add(new QueryItem { WhereName = "Money", Method = Comparison.LessThan, Value = 500, LinkName = "ID" });
View Code

8、测试查看结果

var exp = ExpressionTest.BuildExpression<Book>(queryItems);

var data = Book.GetBooks().AsQueryable();

var book = data.Where(exp);

foreach (var item in book)
{
    Console.WriteLine(JsonConvert.SerializeObject(item));
}
View Code

9、结果

{"Money":600.0,"Sex":"男","ID":50,"Name":"张三"}

 

标签:right,前端,typeof,new,lambda,Expression,public,表达式,left
From: https://www.cnblogs.com/qindr/p/16913812.html

相关文章

  • 前端-git命令
    git工作流:Git工作流指南:Gitflow工作流-久依-博客园(cnblogs.com)#**Git-常用**###常用操作```#拉取仓库代码[email protected]:xlPay/XL......
  • MDH 前端周刊第 77 期:布局动画、Arrow JS、vanilla-extract、antd 5、dumi 2
    MDH前端周刊第77期:布局动画、ArrowJS、vanilla-extract、antd5、dumi2原创 云谦 云谦和他的朋友们 2022-11-2109:25 发表于浙江收录于合集#MDH:前端周刊81个......
  • LC[150] 逆波兰表达式求值
    原题链接:https://leetcode.cn/problems/maximum-subarray/description/慎用自增/自减符号,不要偷懒,写两行代码更为保险以下两段代码的效果是不一样的num[p-1]*=num......
  • 【前端】JS去重
     /**JSON数组去重*@param:[array]jsonArray*@param:[string]唯一的key名,根据此键名进行去重*/exportconstuniqueArray=(array,key)=>{varres......
  • Lamdba表达式
    Lamdba表达式方法引用先来看一下什么是方法引用:方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;注意:实现抽象方......
  • 正则表达式(常用最新版)
    密码【1】密码必须为包含大小写字母和数字的组合,不能使用特殊字符,长度在6-10之间。        /^(?=.*\\d)(?=.*[a-z])(?=.*[A-Z]).{6,10}$/ 【2】密码必须为......
  • jexl3表达式引擎
    Java-ApacheCommonsJexl3-动态表达式判断转自:https://www.cnblogs.com/yqk150/p/14367542.html pom.xml引入maven坐标<!--https://mvnrepository.com/artifact/or......
  • java lambda 表达式 加不加大括号的问题
     1.如果方法体为表达式,算式,可以不加大括号Arrays.sort(startEnd, (o1,o2) -> o1[0] == o2[0] ? o1[1] - o2[1] : o1[0] - o2[0]);2.如果要加大括号,则......
  • 正则表达式
     正则表达式好处:正则的出现,对字符串的复杂操作变得更为简单。特点:将对字符串操作的代码用⼀些符号来表示。只要使用了指定符号,就可以调用底层的代码对字符串进⾏操作。......
  • java 使用正则表达式
    java使用正则表达式正则表达式,又称规则表达式,正则表达式通常被用于判断语句中,来检查某一字符串是否满足某一格式,正则表达式是育有特殊意义的字符串,这些特殊字符串被......