using System.Collections.Generic; using System.Collections.Specialized; using System.Linq.Expressions; using System.Reflection; namespace System.Linq { public static class LinqExtensions { /// 通过页面控件动态构建查询 public static IQueryable WhereDynamic(this IQueryable source, NameValueCollection nameValues) where TSource : class { if (nameValues.Count > 0) { //构建 c=>Body中的c ParameterExpression param = Expression.Parameter(typeof(TSource), "c"); //构建c=>Body中的Body var body = GetExpressoinBody(param, nameValues); if (body != null) { //将二者拼为c=>Body var expression = Expression.Lambda>(body, param); //传到Where中当做参数,类型为Expression> return source.Where(expression); } } return source; } /// 构建body private static Expression GetExpressoinBody(ParameterExpression param, NameValueCollection nameValues) { var list = new List(); if (nameValues.Count > 0) { var plist = param.Type.GetRuntimeProperties().ToDictionary(z => z.Name);//可以加缓存改善性能 foreach (var item in nameValues.AllKeys) if (item.EndsWith(">") || item.EndsWith(">="))//可能大小查询 { bool isEqual = item.EndsWith(">="); string key = isEqual ? item.TrimEnd('=').TrimEnd('>') : item.TrimEnd('>'); if (!plist.ContainsKey(key) || nameValues[item].Length <= 0) continue; var rType = plist[key].GetMethod.ReturnType; if (rType == typeof(string)) continue; var e1 = Expression.Property(param, key); object dValue; if (TryParser(nameValues[item], rType, out dValue)) //list.Add(Expression.GreaterThan(e1, Expression.Constant(dValue, rType))); list.Add(AddGreaterGreaterThan(e1, Expression.Constant(dValue, rType), isEqual)); else if (plist[key].GetMethod.ReturnType.GenericTypeArguments.Count() > 0 && TryParser(nameValues[item], plist[key].GetMethod.ReturnType.GenericTypeArguments[0], out dValue)) //list.Add(Expression.GreaterThan(e1, Expression.Constant(dValue, rType))); list.Add(AddGreaterGreaterThan(e1, Expression.Constant(dValue, rType), isEqual)); else if (rType == typeof(DateTime?)) { DateTime enddate = nameValues[item].ToDateTime().GetValueOrDefault(); //list.Add(Expression.GreaterThan(e1, Expression.Constant(enddate, typeof(DateTime?)))); list.Add(AddGreaterGreaterThan(e1, Expression.Constant(enddate, typeof(DateTime?)), isEqual)); } } else if (item.EndsWith("<") || item.EndsWith("<="))//可能大小查询 { bool isEqual = item.EndsWith("<="); string key = isEqual ? item.TrimEnd('=').TrimEnd('<') : item.TrimEnd('<'); if (!plist.ContainsKey(key) || nameValues[item].Length <= 0) continue; var rType = plist[key].GetMethod.ReturnType; if (rType == typeof(string)) continue; var e1 = Expression.Property(param, key); object dValue; if (TryParser(nameValues[item], rType, out dValue)) { if (rType == typeof(DateTime)) dValue = ((DateTime)dValue).AddDays(1); //list.Add(Expression.LessThan(e1, Expression.Constant(dValue, rType))); list.Add(AddGreaterLessThan(e1, Expression.Constant(dValue, rType), isEqual)); } else if (plist[key].GetMethod.ReturnType.GenericTypeArguments.Count() > 0 && TryParser(nameValues[item], plist[key].GetMethod.ReturnType.GenericTypeArguments[0], out dValue)) { if (plist[key].GetMethod.ReturnType.GenericTypeArguments[0] == typeof(DateTime)) dValue = ((DateTime)dValue).AddDays(1); //list.Add(Expression.LessThan(e1, Expression.Constant(dValue, rType))); list.Add(AddGreaterLessThan(e1, Expression.Constant(dValue, rType), isEqual)); } else if (rType == typeof(DateTime?)) { DateTime enddate = nameValues[item].ToDateTime().GetValueOrDefault().AddDays(1); //list.Add(Expression.LessThan(e1, Expression.Constant(enddate, typeof(DateTime?)))); list.Add(AddGreaterLessThan(e1, Expression.Constant(enddate, typeof(DateTime?)), isEqual)); } } else if (plist.ContainsKey(item) && nameValues[item].Length > 0) { var e1 = Expression.Property(param, item); var rType = plist[item].GetMethod.ReturnType; if (rType == typeof(string))//可能是like查询 { var value = nameValues[item].Trim('%'); var e2 = Expression.Constant(value, rType); if (nameValues[item].StartsWith("%") && nameValues[item].EndsWith("%")) list.Add(Expression.Call(e1, "Contains", null, new Expression[] { e2 })); else if (nameValues[item].StartsWith("%")) list.Add(Expression.Call(e1, "EndsWith", null, new Expression[] { e2 })); else if (nameValues[item].EndsWith("%")) list.Add(Expression.Call(e1, "StartsWith", null, new Expression[] { e2 })); else list.Add(Expression.Equal(e1, e2)); } else if (nameValues[item].IndexOf(",") > 0)//可能是in查询 { if (rType == typeof(short)) { var searchList = TryParser(nameValues[item]); if (searchList.Any()) list.Add(Expression.Call(Expression.Constant(searchList, rType), "Contains", null, new Expression[] { e1 })); } else if (rType == typeof(int)) { var searchList = TryParser(nameValues[item]); if (searchList.Any()) list.Add(Expression.Call(Expression.Constant(searchList, rType), "Contains", null, new Expression[] { e1 })); } else if (rType == typeof(long)) { var searchList = TryParser(nameValues[item]); if (searchList.Any()) list.Add(Expression.Call(Expression.Constant(searchList, rType), "Contains", null, new Expression[] { e1 })); } } else { object dValue; if (TryParser(nameValues[item], rType, out dValue)) list.Add(Expression.Equal(e1, Expression.Constant(dValue, rType))); } } } return list.Count > 0 ? list.Aggregate(Expression.AndAlso) : null; } private static List TryParser(string value) { string[] searchArray = value.Split(','); List dList = new List(); foreach (var l in searchArray) { try { T dValue = (T)Convert.ChangeType(l, typeof(T)); dList.Add(dValue); } catch { } } return dList; } private static bool TryParser(string value, Type outType, out object dValue) { try { dValue = Convert.ChangeType(value, outType); return true; } catch { dValue = null; return false; } } //大于 private static Expression AddGreaterGreaterThan(Expression exleft, Expression exright, bool Equal) { if (Equal) { return Expression.GreaterThanOrEqual(exleft, exright); } else { return Expression.GreaterThan(exleft, exright); } } //大于 private static Expression AddGreaterLessThan(Expression exleft, Expression exright, bool Equal) { if (Equal) { return Expression.LessThanOrEqual(exleft, exright); } else { return Expression.LessThan(exleft, exright); } } /// /// 从 System.Collections.Generic.IQueryable`1 创建一个 System.Collections.Generic.List`1。并在集合末尾添加一个默认值为空的TSource实例 /// /// source 中的元素的类型。 /// 要从其创建 System.Collections.Generic.List`1 的 System.Collections.Generic.IEnumerable`1。 /// 一个包含输入序列中元素的 System.Collections.Generic.List`1。 public static List ToListAndAddEmpty(this IQueryable source) where TSource : class { List list = source.ToList(); TSource addmodel = Activator.CreateInstance(); list.Add(addmodel); return list; } /// /// 从 System.Collections.Generic.IEnumerable`1 创建一个 System.Collections.Generic.List`1。并在集合末尾添加一个默认值为空的TSource实例 /// /// source 中的元素的类型。 /// 要从其创建 System.Collections.Generic.List`1 的 System.Collections.Generic.IEnumerable`1。 /// 一个包含输入序列中元素的 System.Collections.Generic.List`1。 public static List ToListAndAddEmpty(this IEnumerable source) where TSource : class { List list = source.ToList(); TSource addmodel = Activator.CreateInstance(); list.Add(addmodel); return list; } /// /// 动态模糊查询 /// /// source 中的元素的类型。 /// 一个要模糊查找的值序列。 /// 由 keySelector 表示的函数返回的键类型。 /// 查询关键字(动态模糊在首或尾部添加%) /// 查询字段 /// 查询字段Lamvda表达式(支持多表导航查询) /// 一个 System.Linq.IOrderedQueryable`1,根据键对其元素模糊查找。 public static IQueryable LikeQueryable(this IQueryable source, string keyword, params Expression>[] keySelector) { try { var paramT = Expression.Parameter(typeof(TSource), "c");//c=> Expression body = null; var list = new List(); foreach (var item in keySelector) { string[] paramKs = item.Body.ToString().Split('.'); var e1 = Expression.Property(paramT, paramKs[1]);//c.user for (int i = 2; i < paramKs.Count(); i++) { e1 = Expression.Property(e1, paramKs[i]);//c.user.ID } if (e1.Type == typeof(string)) { var value = keyword.Trim('%'); var e2 = Expression.Constant(value, typeof(string)); if (keyword.StartsWith("%") && keyword.EndsWith("%")) list.Add(Expression.Call(e1, "Contains", null, new Expression[] { e2 })); else if (keyword.StartsWith("%")) list.Add(Expression.Call(e1, "EndsWith", null, new Expression[] { e2 })); else if (keyword.EndsWith("%")) list.Add(Expression.Call(e1, "StartsWith", null, new Expression[] { e2 })); else list.Add(Expression.Equal(e1, e2)); } } body = list.Count > 0 ? list.Aggregate(Expression.OrElse) : null; //构建c=>Body中的Body if (body != null) { //将二者拼为c=>Body var expression = Expression.Lambda>(body, paramT); //传到Where中当做参数,类型为Expression> source = source.Where(expression); } } catch { } return source; } /// /// 动态模糊查询 /// /// source 中的元素的类型。 /// 一个要模糊查找的值序列。 /// 查询关键字(动态模糊在首或尾部添加%) /// 查询字段 /// 查询字段Lamvda表达式(支持多表导航查询) /// 一个 System.Linq.IOrderedQueryable`1,根据键对其元素模糊查找。 public static IQueryable LikeQueryable(this IQueryable source, string keyword, params string[] keyfiled) { try { var paramT = Expression.Parameter(typeof(TSource), "c");//c=> Expression body = null; var list = new List(); foreach (var item in keyfiled) { string[] paramKs = item.Split('.'); var e1 = Expression.Property(paramT, paramKs[0]);//c.user for (int i = 1; i < paramKs.Count(); i++) { e1 = Expression.Property(e1, paramKs[i]);//c.user.ID } if (e1.Type == typeof(string)) { var value = keyword.Trim('%'); var e2 = Expression.Constant(value, typeof(string)); if (keyword.StartsWith("%") && keyword.EndsWith("%")) list.Add(Expression.Call(e1, "Contains", null, new Expression[] { e2 })); else if (keyword.StartsWith("%")) list.Add(Expression.Call(e1, "EndsWith", null, new Expression[] { e2 })); else if (keyword.EndsWith("%")) list.Add(Expression.Call(e1, "StartsWith", null, new Expression[] { e2 })); else list.Add(Expression.Equal(e1, e2)); } } body = list.Count > 0 ? list.Aggregate(Expression.OrElse) : null; //构建c=>Body中的Body if (body != null) { //将二者拼为c=>Body var expression = Expression.Lambda>(body, paramT); //传到Where中当做参数,类型为Expression> source = source.Where(expression); } } catch { } return source; } /// /// 外键表动态模糊查询 /// /// source 中的元素的类型。 /// 一个要模糊查找的值序列。 /// 由 keySelector 表示的函数返回的键类型。 /// 查询关键字(动态模糊在首或尾部添加%) /// 查询字段 /// 查询字段Lamvda表达式(支持多表导航查询) /// 一个 System.Linq.IOrderedQueryable`1,根据键对其元素模糊查找。 public static IQueryable LikeQueryable(this IQueryable source, string keyword, string keyfiled, params Expression>[] keySelector) { try { var paramT = Expression.Parameter(typeof(TSource), "c");//c=> Expression body = null; var list = new List(); foreach (var item in keySelector) { string[] paramKs = item.Body.ToString().Split('.'); var e1 = Expression.Property(paramT, paramKs[1]);//c.user for (int i = 2; i < paramKs.Count(); i++) { e1 = Expression.Property(e1, paramKs[i]);//c.user.ID } e1 = Expression.Property(e1, keyfiled);//c.user.ID if (e1.Type == typeof(string)) { var value = keyword.Trim('%'); var e2 = Expression.Constant(value, typeof(string)); if (keyword.StartsWith("%") && keyword.EndsWith("%")) list.Add(Expression.Call(e1, "Contains", null, new Expression[] { e2 })); else if (keyword.StartsWith("%")) list.Add(Expression.Call(e1, "EndsWith", null, new Expression[] { e2 })); else if (keyword.EndsWith("%")) list.Add(Expression.Call(e1, "StartsWith", null, new Expression[] { e2 })); else list.Add(Expression.Equal(e1, e2)); } } body = list.Count > 0 ? list.Aggregate(Expression.OrElse) : null; //构建c=>Body中的Body if (body != null) { //将二者拼为c=>Body var expression = Expression.Lambda>(body, paramT); //传到Where中当做参数,类型为Expression> source = source.Where(expression); } } catch { } return source; } /// /// 动态排序 /// /// source 中的元素的类型。 /// 一个要排序查找的值序列。 /// 排序字段 /// 排序类型0不排序,1升序,2降序 /// 一个 System.Linq.IOrderedQueryable`1,根据键对其元素模糊查找。 public static IQueryable OrderByQueryable(this IQueryable source, string keyfiled, int type) { try { if (type == 0) return source;//不排序 var paramT = Expression.Parameter(typeof(TSource), "c");//c=> string[] paramKs = keyfiled.Split('.'); var e1 = Expression.Property(paramT, paramKs[0]);//c.user for (int i = 1; i < paramKs.Count(); i++) { e1 = Expression.Property(e1, paramKs[i]);//c.user.ID } dynamic expression = Expression.Lambda(e1, paramT); switch (type) { case 1: source = Queryable.OrderBy(source, expression); break; case 2: source = Queryable.OrderByDescending(source, expression); break; default: break; } } catch { } return source; } /// /// 动态排序 /// /// source 中的元素的类型。 /// 一个要排序查找的值序列。 /// 排序字段 /// 排序类型0不排序,1升序,2降序 /// 一个 System.Linq.IOrderedQueryable`1,根据键对其元素模糊查找。 public static IEnumerable OrderByQueryable(this IEnumerable source, string keyfiled, int type) { try { if (type == 0) return source;//不排序 var paramT = Expression.Parameter(typeof(TSource), "c");//c=> string[] paramKs = keyfiled.Split('.'); var e1 = Expression.Property(paramT, paramKs[0]);//c.user for (int i = 1; i < paramKs.Count(); i++) { e1 = Expression.Property(e1, paramKs[i]);//c.user.ID } dynamic expression = Expression.Lambda(e1, paramT); switch (type) { case 1: source = Queryable.OrderBy(source.AsQueryable(), expression); break; case 2: source = Queryable.OrderByDescending(source.AsQueryable(), expression); break; default: break; } } catch { } return source; } } }