C#中Lambda表达式树Expression实现多过滤条件多排序
1.编写参数类SearchCondition可以传入多个过滤条件和多个排序条件

2.编写方法ConvertToLamdaExpression实现将多个查询条件
// // 摘要: // 查询条件转Lamda表达式 // // 类型参数: // T: // 数据类型 // // 返回结果: // 表达式 public Expression<Func<T, bool>> ConvertToLamdaExpression<T>() { Expression<Func<T, bool>> expression = PredicateExtension.True<T>(); foreach (SearchItem searchItem in SearchItems) { string field = searchItem.Field; SearchMethod searchMethod = searchItem.SearchMethod; DataType dataType = searchItem.DataType; object value = searchItem.Value; if (string.IsNullOrEmpty(field) || value == null) { continue; } Expression expression2 = null; ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p"); Expression expression3 = Expression.PropertyOrField(parameterExpression, field); Expression expression4 = Expression.Constant(value); if (expression4.Type.Equals(typeof(JsonElement))) { expression4 = Expression.Constant(value.ToString()); } Guid result3; if (expression3.Type.Equals(typeof(OperationType))) { expression4 = Expression.Constant((OperationType)int.Parse(value.ToString()), typeof(OperationType)); } else if (expression3.Type.Equals(typeof(DateTime)) && searchMethod != SearchMethod.BetweenAnd) { expression4 = Expression.Constant(DateTime.Parse(value.ToString()), typeof(DateTime)); } else if (expression3.Type.Equals(typeof(DateTime?)) && searchMethod != SearchMethod.BetweenAnd) { expression4 = Expression.Constant(DateTime.Parse(value.ToString()), typeof(DateTime?)); } else if (expression3.Type.Equals(typeof(Guid))) { if (Guid.TryParse(value.ToString(), out var _)) { expression4 = Expression.Constant(Guid.Parse(value.ToString()), typeof(Guid)); } } else if (!expression3.Type.Equals(typeof(Guid?))) { expression4 = (expression3.Type.Equals(typeof(float)) ? Expression.Constant(float.Parse(value.ToString()), typeof(float)) : (expression3.Type.Equals(typeof(float?)) ? Expression.Constant(float.Parse(value.ToString()), typeof(float?)) : (expression3.Type.Equals(typeof(double)) ? Expression.Constant(double.Parse(value.ToString()), typeof(double)) : (expression3.Type.Equals(typeof(double?)) ? Expression.Constant(double.Parse(value.ToString()), typeof(double?)) : (expression3.Type.Equals(typeof(int)) ? Expression.Constant(int.Parse(value.ToString()), typeof(int)) : (expression3.Type.Equals(typeof(int?)) ? Expression.Constant(int.Parse(value.ToString()), typeof(int?)) : (expression3.Type.Equals(typeof(bool)) ? Expression.Constant(bool.Parse(value.ToString()), typeof(bool)) : (expression3.Type.Equals(typeof(bool?)) ? Expression.Constant(bool.Parse(value.ToString()), typeof(bool?)) : ((!expression3.Type.IsEnum) ? Expression.Constant(value.ToString(), typeof(string)) : ((!Enum.TryParse(expression3.Type, value.ToString(), out object result2)) ? Expression.Constant(value.ToString(), typeof(string)) : Expression.Constant(result2, expression3.Type))))))))))); } else if (Guid.TryParse(value.ToString(), out result3)) { expression4 = Expression.Constant(Guid.Parse(value.ToString()), typeof(Guid?)); } switch (searchMethod) { case SearchMethod.Equal: expression2 = Expression.Equal(expression3, expression4); break; case SearchMethod.LessThan: expression2 = Expression.LessThan(expression3, expression4); break; case SearchMethod.LessThanOrEqual: expression2 = Expression.LessThanOrEqual(expression3, expression4); break; case SearchMethod.GreaterThan: expression2 = Expression.GreaterThan(expression3, expression4); break; case SearchMethod.GreaterThanOrEqual: expression2 = Expression.GreaterThanOrEqual(expression3, expression4); break; case SearchMethod.BetweenAnd: { string[] array = value.ToString().Split(','); ConstantExpression right = ((dataType == DataType.DateTime) ? Expression.Constant(Convert.ToDateTime(array[0]), typeof(DateTime)) : Expression.Constant(array[0], typeof(string))); ConstantExpression right2 = ((dataType == DataType.DateTime) ? Expression.Constant(Convert.ToDateTime(array[1]), typeof(DateTime)) : Expression.Constant(array[1], typeof(string))); expression2 = Expression.GreaterThanOrEqual(expression3, right); Expression<Func<T, bool>> second = Expression.Lambda<Func<T, bool>>(expression2, new ParameterExpression[1] { parameterExpression }); expression = expression.And(second); expression2 = Expression.LessThanOrEqual(expression3, right2); second = Expression.Lambda<Func<T, bool>>(expression2, new ParameterExpression[1] { parameterExpression }); expression = expression.And(second); expression2 = null; break; } case SearchMethod.Like: { MethodInfo method5 = ((dataType == DataType.Int) ? typeof(List<int>).GetMethod("Contains", new Type[1] { typeof(List<int>) }) : typeof(string).GetMethod("Contains", new Type[1] { typeof(string) })); expression2 = Expression.Call(expression3, method5, expression4); break; } case SearchMethod.RightLike: { MethodInfo method2 = ((dataType == DataType.Int) ? typeof(List<int>).GetMethod("Contains", new Type[1] { typeof(List<int>) }) : typeof(string).GetMethod("EndsWith", new Type[1] { typeof(string) })); expression2 = Expression.Call(expression3, method2, expression4); break; } case SearchMethod.LeftLike: { MethodInfo method6 = ((dataType == DataType.Int) ? typeof(List<int>).GetMethod("Contains", new Type[1] { typeof(List<int>) }) : typeof(string).GetMethod("StartsWith", new Type[1] { typeof(string) })); expression2 = Expression.Call(expression3, method6, expression4); break; } case SearchMethod.Include: { MethodInfo method4 = typeof(Enumerable).GetMethods().First((MethodInfo m) => m.Name == "Contains" && m.GetParameters().Length == 2).MakeGenericMethod(typeof(string)); ConstantExpression arg = Expression.Constant(value.ToString().Split(",").ToList(), typeof(IEnumerable<string>)); Expression arg2 = Expression.Call(expression3, expression3.Type.GetMethod("ToString", Type.EmptyTypes)); expression2 = Expression.Call(method4, arg, arg2); break; } case SearchMethod.NotInclude: { MethodInfo method3 = typeof(Enumerable).GetMethods().First((MethodInfo m) => m.Name == "Contains" && m.GetParameters().Length == 2).MakeGenericMethod(typeof(string)); Expression.Constant(value.ToString().Split(",").ToList(), typeof(IEnumerable<string>)); Expression expression5 = Expression.Call(expression3, expression3.Type.GetMethod("ToString", Type.EmptyTypes)); expression2 = Expression.Not(Expression.Call(method3, expression5, expression5)); break; } case SearchMethod.OrLike: { MethodInfo method = ((dataType == DataType.Int) ? typeof(List<int>).GetMethod("Contains", new Type[1] { typeof(List<int>) }) : typeof(string).GetMethod("Contains", new Type[1] { typeof(string) })); expression2 = Expression.Call(expression3, method, expression4); Expression<Func<T, bool>> second = Expression.Lambda<Func<T, bool>>(expression2, new ParameterExpression[1] { parameterExpression }); expression = expression.Or(second); expression2 = null; break; } case SearchMethod.NotEqual: expression2 = Expression.NotEqual(expression3, expression4); break; } if (expression2 != null) { Expression<Func<T, bool>> second2 = Expression.Lambda<Func<T, bool>>(expression2, new ParameterExpression[1] { parameterExpression }); expression = expression.And(second2); } } return expression; } public Expression<Func<List<T>, bool>> BuildContainsExpression<T>(T value) { ParameterExpression parameterExpression = Expression.Parameter(typeof(List<T>), "list"); ConstantExpression constantExpression = Expression.Constant(value, typeof(T)); return Expression.Lambda<Func<List<T>, bool>>(Expression.Call(parameterExpression, "Contains", null, constantExpression), new ParameterExpression[1] { parameterExpression }); }
3.条件过滤调用时需使用Compile方法将类型转换一下,否则提示如下错误

#region 条件过滤 searchCondition.AddDefaultSearchItem(false); var where = searchCondition.ConvertToLamdaExpression<WorkStationInfo>(); allWorkStations = allWorkStations.Where(where.Compile()); #endregion
4.编写方法ConvertToOrderLamdaExpression将多个查询条件转换为lambda
public List<Tuple<Expression<Func<T, object>>, OrderByType>> ConvertToOrderLamdaExpression<T>() { List<Tuple<Expression<Func<T, object>>, OrderByType>> list = new List<Tuple<Expression<Func<T, object>>, OrderByType>>(); List<SortItem> sortItem = SortItem; if (sortItem != null && sortItem.Count > 0) { foreach (SortItem item2 in SortItem) { ParameterExpression parameterExpression = Expression.Parameter(typeof(T), "p"); string name = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(item2.Field.ToLower()).First().ToString() .ToUpper() + item2.Field.Substring(1); Expression<Func<T, object>> item = Expression.Lambda<Func<T, object>>(Expression.Convert(Expression.Property(parameterExpression, typeof(T).GetProperty(name)), typeof(object)), new ParameterExpression[1] { parameterExpression }); list.Add(Tuple.Create(item, item2.OrderType)); } } return list; }
5.排序调用
#region 排序 var order = searchCondition.ConvertToOrderLamdaExpression<WorkStationInfo>(); int index = 0; order.ForEach(item => { if (item.Item2 == OrderByType.Asc) { if (index == 0) { allWorkStations = allWorkStations.OrderBy(item.Item1.Compile()); } else { allWorkStations = (allWorkStations as IOrderedEnumerable<WorkStationInfo>).ThenBy(item.Item1.Compile()); } } else { if (index == 0) { allWorkStations = allWorkStations.OrderByDescending(item.Item1.Compile()); } else { allWorkStations = (allWorkStations as IOrderedEnumerable<WorkStationInfo>).ThenByDescending(item.Item1.Compile()); } } index++; }); #endregion
ThenBy在实际使用中必须使用链式编程的方法写在orderby后边,所以通过将类型转换为IOrderedEnumerable<>后在thenby实现与orderby分开排序。
2025-05-23 11:30:00【出处】:https://www.cnblogs.com/jiangyuhu/p/18892730
=======================================================================================
如果,您希望更容易地发现我的新博客,不妨点击一下绿色通道的【关注我】。(●'◡'●)
因为,我的写作热情也离不开您的肯定与支持,感谢您的阅读,我是【Jack_孟】!
本文来自博客园,作者:jack_Meng,转载请注明原文链接:https://www.cnblogs.com/mq0036/p/18892786
【免责声明】本文来自源于网络,如涉及版权或侵权问题,请及时联系我们,我们将第一时间删除或更改!

浙公网安备 33010602011771号