动态拼接linq Where条件

    

具体使用

定义一个动态拼接lambda 的帮助类

using System.Linq.Expressions;
using System.Reflection;

namespace Utils
{
    public class Filter
    {
        public string Key { get; set; } //过滤的关键字
        public string Value { get; set; } //过滤的值
        public string Contract { get; set; }// 过滤的约束 比如:'<' '<=' '>' '>=' 'like'等
    }

    public static class DynamicLinq
    {
        /// <summary>
        /// 创建lambda中的参数,即c=>c.xxx==xx 中的c
        /// </summary>
        public static ParameterExpression CreateLambdaParam<T>(string name)
        {
            return Expression.Parameter(typeof(T), name);
        }

        /// <summary>
        /// 创建linq表达示的body部分,即c=>c.xxx==xx 中的c.xxx==xx
        /// </summary>
        public static Expression GenerateBody<T>(this ParameterExpression param, Filter filterObj)
        {
            PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
            //组装左边
            Expression left = Expression.Property(param, property);
            //组装右边
            Expression right = null;

            //todo: 下面根据需要,扩展自己的类型
            if (property.PropertyType == typeof(int))
            {
                right = Expression.Constant(int.Parse(filterObj.Value));
            }
            else if (property.PropertyType == typeof(short))
            {
                right = Expression.Constant(short.Parse(filterObj.Value));
            }
            else if (property.PropertyType == typeof(short))
            {
                right = Expression.Constant((short)short.Parse(filterObj.Value), typeof(short));
            }
            else if (property.PropertyType == typeof(DateTime?))
            {
                right = Expression.Constant((DateTime?)DateTime.Parse(filterObj.Value), typeof(DateTime?));
            }
            else if (property.PropertyType == typeof(DateTime))
            {
                right = Expression.Constant(DateTime.Parse(filterObj.Value));
            }
            else if (property.PropertyType == typeof(string))
            {
                right = Expression.Constant((filterObj.Value));
            }
            else if (property.PropertyType == typeof(decimal))
            {
                right = Expression.Constant(decimal.Parse(filterObj.Value));
            }
            else if (property.PropertyType == typeof(Guid))
            {
                right = Expression.Constant(Guid.Parse(filterObj.Value));
            }
            else if (property.PropertyType == typeof(bool))
            {
                right = Expression.Constant(filterObj.Value.Equals("1"));
            }
            else
            {
                throw new Exception("暂不能解析该Key的类型");
            }

            //todo: 下面根据需要扩展自己的比较
            Expression filter = Expression.Equal(left, right);
            switch (filterObj.Contract)
            {
                case "<=":
                    filter = Expression.LessThanOrEqual(left, right);
                    break;

                case "==": //bool 类型
                    filter = Expression.Call(left, typeof(Boolean).GetMethod("Equals", new[] { typeof(Boolean) }),
                                 Expression.Constant(filterObj.Value.Equals("1")));
                    break;

                case "==="://string 类型
                    filter = Expression.Call(left, typeof(string).GetMethod("Equals", new[] { typeof(string) }),
                                      Expression.Constant(filterObj.Value));
                    break;

                case "==i":  //int 类型
                    filter = Expression.Call(left, typeof(int).GetMethod("Equals", new[] { typeof(int) }),
                                      Expression.Constant(Convert.ToInt32(filterObj.Value)));
                    break;

                case "==is":  //short 类型
                    filter = Expression.Call(left, typeof(short).GetMethod("Equals", new[] { typeof(short) }),
                                      Expression.Constant(Convert.ToInt16(filterObj.Value)));
                    break;

                case "<":
                    filter = Expression.LessThan(left, right);
                    break;

                case ">":
                    filter = Expression.GreaterThan(left, right);
                    break;

                case ">=":
                    filter = Expression.GreaterThanOrEqual(left, right);
                    break;

                case "like":
                    filter = Expression.Call(left, typeof(string).GetMethod("Contains", new[] { typeof(string) }),
                                 Expression.Constant(filterObj.Value));
                    break;

                case "!=":
                    filter = Expression.NotEqual(left, Expression.Constant(filterObj.Value));
                    break;
            }

            return filter;
        }

        /// <summary>
        /// 创建完整的lambda,即c=>c.xxx==xx
        /// </summary>
        public static LambdaExpression GenerateLambda(this ParameterExpression param, Expression body)
        {
            return Expression.Lambda(body, param);
        }

        /// <summary>
        /// 创建完整的lambda,为了兼容EF中的where语句
        /// </summary>
        public static Expression<Func<T, bool>> GenerateTypeLambda<T>(this ParameterExpression param, Expression body)
        {
            return (Expression<Func<T, bool>>)(param.GenerateLambda(body));
        }

        public static Expression AndAlso(this Expression expression, Expression expressionRight)
        {
            return Expression.AndAlso(expression, expressionRight);
        }

        public static Expression Or(this Expression expression, Expression expressionRight)
        {
            return Expression.Or(expression, expressionRight);
        }

        public static Expression And(this Expression expression, Expression expressionRight)
        {
            return Expression.And(expression, expressionRight);
        }
    }

    public static class DynamicExtention
    {
        public static IQueryable<T> Where<T>(this IQueryable<T> query, Filter[] filters)
        {
            var param = DynamicLinq.CreateLambdaParam<T>("c");
            Expression body = Expression.Constant(true); //初始默认一个true
            Expression bodykey; //初始默认一个true
            foreach (var filter in filters)
            {
                body = body.AndAlso(param.GenerateBody<T>(filter)); //这里可以根据需要自由组合
            }

            var lambda = param.GenerateTypeLambda<T>(body); //最终组成lambda
            return query.Where(lambda);
        }
    }
}

 在方法中使用

 List<Filter> filters = new List<Filter>();
    
filters.Add(new Filter { Key = "LastEditAt", Value = DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd"), Contract = ">=" });     
filters.Add(new Filter { Key = "Carrier", Value = HousingID, Contract = "like" });
filters.Add(new Filter { Key = "OperationNumberId", Value = option.ToString(), Contract = "==is" });

  var area = _context.Tables.Where(filters.ToArray()).ToList();

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值