基于网上找的一段代码进行修改,目前扩展了NotContains方法的实现
using System; using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; using ZW.CateringSystem.Common.ConvertHelper; namespace ZW.CateringSystem.Common.LinqHelper { #region 动态linq帮助类,连接符号,运算符号 /// <summary> /// 动态linq工厂 /// </summary> public static class DynamicLinqFactory { /// <summary> /// 生成lambd表达式 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="propertyStr"></param> /// <returns></returns> public static Expression<Func<TSource, bool>> CreateLambda<TSource>(string propertyStr) { // 设置自定义lanbd // 定义 lanbd 种子(p=> xxxxxx)中的 p var parameter = Expression.Parameter(typeof(TSource), "p"); var strArr = SpiltStrings(propertyStr); // 第一个判断条件,固定一个判断条件作为最左边 Expression mainExpressin = ExpressionStudio(null, strArr.FirstOrDefault(x => x.LinkSymbol == LinkSymbol.Empty), parameter); // 将需要放置在最左边的判断条件从列表中去除,因为已经合成到表达式最左边了 strArr.Remove(strArr.FirstOrDefault(x => x.LinkSymbol == LinkSymbol.Empty)); foreach (var x in strArr) { mainExpressin = ExpressionStudio(mainExpressin, x, parameter); } return mainExpressin.ToLambda<Func<TSource, bool>>(parameter); } /// <summary> /// 组合条件判断表达式 /// </summary> /// <param name="left">左边的表达式</param> /// <param name="DynamicLinq"></param> /// <param name="key"></param> /// <returns></returns> public static Expression ExpressionStudio(Expression left, DynamicLinqHelper DynamicLinq, ParameterExpression key) { Expression mainExpression = key; var properties = DynamicLinq.Left.Split('.'); // 从1开始,是不想用自定义种子,外层种子已经定义好了 // 暂时也不会有多个自定义种子,先这样 for (var i = 1; i < properties.Length; i++) { mainExpression = mainExpression.Property(properties[i]); } left = left == null // 如果左边表达式为空,则当前的表达式就为最左边 ? ChangeOperationSymbol(DynamicLinq.OperationSymbol, mainExpression, DynamicLinq.Right) // 如果不为空,则将当前的表达式连接到左边 : ChangeLinkSymbol(DynamicLinq.LinkSymbol, left, ChangeOperationSymbol(DynamicLinq.OperationSymbol, mainExpression, DynamicLinq.Right)); return left; } /// <summary> /// 将字符串装换成动态帮助类(内含递归) /// </summary> public static List<DynamicLinqHelper> SpiltStrings(string propertyStr) { // 定义返回用List var outList = new List<DynamicLinqHelper>(); // 当最后已经没有连接运算符的时候,进入该条件 if (!propertyStr.Contains("&") & !propertyStr.Contains("|")) { // 当前的条件是不具备连接符号的 var lastStr = propertyStr.Trim().Split(' '); if (lastStr.Length == 1) { outList.Add(new DynamicLinqHelper { LinkSymbol = LinkSymbol.Empty, Left = lastStr[0], Right = "", OperationSymbol = ChangeOperationSymbol("null") }); return outList; } outList.Add(new DynamicLinqHelper { LinkSymbol = LinkSymbol.Empty, Left = lastStr[0], Right = lastStr[2], OperationSymbol = ChangeOperationSymbol(lastStr[1]) }); return outList; } // 判断当前 & | 哪个符号在最后一个判断逻辑内 var key = propertyStr.LastIndexOf('&') > propertyStr.LastIndexOf('|') ? '&' : '|'; var nowStrArr = propertyStr.Substring(propertyStr.LastIndexOf(key)).Trim().Split(' '); outList.Add(new DynamicLinqHelper { LinkSymbol = ChangeLinkSymbol(nowStrArr[0]), Left = nowStrArr[1], OperationSymbol = ChangeOperationSymbol(nowStrArr[2]), Right = nowStrArr[3] }); // 将剩余部分继续切割 propertyStr = propertyStr.Substring(0, propertyStr.LastIndexOf(key)).Trim(); // 递归 由后彺前 outList.AddRange(SpiltStrings(propertyStr)); return outList; } /// <summary> /// 将字符串符号转成运算枚举符号 /// </summary> public static LinkSymbol ChangeLinkSymbol(string str) { // 这里判断链接符号 // 当链接符号为Empty,则说明当前对象为表达式的最左边 // 如果一个表达式出现两次链接符号为空,则说明输入的字符串格式有问题 switch (str) { case "|": return LinkSymbol.OrElse; case "&": return LinkSymbol.AndAlso; default: return LinkSymbol.Empty; } } /// <summary> /// 将运算枚举符号转成具体使用方法 /// </summary> public static Expression ChangeLinkSymbol(LinkSymbol Symbol, Expression left, Expression right) { switch (Symbol) { case LinkSymbol.OrElse: return left.OrElse(right); case LinkSymbol.AndAlso: return left.AndAlso(right); default: return left; } } /// <summary> /// 将字符串符号转成运算枚举符号 /// </summary> public static OperationSymbol ChangeOperationSymbol(string str) { switch (str) { case "<": return OperationSymbol.LessThan; case "<=": return OperationSymbol.LessThanOrEqual; case ">": return OperationSymbol.GreaterThan; case ">=": return OperationSymbol.GreaterThanOrEqual; case "==": return OperationSymbol.Equal; case "!=": return OperationSymbol.NotEqual; case "Contains": return OperationSymbol.Contains; case "NotContains": return OperationSymbol.NotContains; case "null": return OperationSymbol.Null; } throw new Exception("OperationSymbol IS NULL"); } /// <summary> /// 将运算枚举符号转成具体使用方法 /// </summary> public static Expression ChangeOperationSymbol(OperationSymbol symbol, Expression key, object right) { if (symbol == OperationSymbol.Null) { return key; } // 将右边数据类型强行转换成左边一样的类型 // 两者如果Type不匹配则无法接下去的运算操作,抛出异常 object newTypeRight; if (right.ToString() == "null") { newTypeRight = null; } else { //判断key.Type的类型,调用不同的方法进行转换; var t = key.Type; newTypeRight = ConvertionExtensions.ChangeType(right, key.Type); } // 根据当前枚举类别判断使用那种比较方法 switch (symbol) { case OperationSymbol.Equal: return key.Equal(Expression.Constant(newTypeRight)); case OperationSymbol.GreaterThan: return key.GreaterThan(Expression.Constant((newTypeRight))); case OperationSymbol.GreaterThanOrEqual: return key.GreaterThanOrEqual(Expression.Constant(newTypeRight)); case OperationSymbol.LessThan: return key.LessThan(Expression.Constant((newTypeRight))); case OperationSymbol.LessThanOrEqual: return key.LessThanOrEqual(Expression.Constant((newTypeRight))); case OperationSymbol.NotEqual: return key.NotEqual(Expression.Constant(newTypeRight)); case OperationSymbol.Contains: return key.Contains(Expression.Constant(newTypeRight)); case OperationSymbol.NotContains: // 不包含 return Expression.Not(key.Contains(Expression.Constant(newTypeRight))); } throw new Exception("OperationSymbol IS NULL"); } } /// <summary> /// 动态linq帮助类 /// </summary> public class DynamicLinqHelper { [Display(Name = "左")] public string Left { get; set; } [Display(Name = "右")] public string Right { get; set; } [Display(Name = "运算符")] public OperationSymbol OperationSymbol { get; set; } [Display(Name = "连接符")] public LinkSymbol LinkSymbol { get; set; } } /// <summary> /// 连接符枚举(将来可能会包含 括号 ) /// </summary> public enum LinkSymbol { [Display(Name = "&&")] AndAlso, [Display(Name = "||")] OrElse, [Display(Name = "空")] Empty } /// <summary> /// 常用比较运算符 > , >= , == , < , <= , != ,Contains /// </summary> public enum OperationSymbol { [Display(Name = "Contains")] Contains, [Display(Name = "NotContains")] NotContains, [Display(Name = ">")] GreaterThan, [Display(Name = ">=")] GreaterThanOrEqual, [Display(Name = "<")] LessThan, [Display(Name = "<=")] LessThanOrEqual, [Display(Name = "==")] Equal, [Display(Name = "!=")] NotEqual, [Display(Name = "null")] Null } #endregion /// <summary> /// Linq扩展 /// </summary> public static class ExpressionExtensions { #region 常用扩展方法 /// <summary> /// 调用内部方法 /// </summary> public static Expression Call(this Expression instance, string methodName, params Expression[] arguments) { return Expression.Call(instance, instance.Type.GetMethod(methodName), arguments); } /// <summary> /// 获取内部成员 /// </summary> public static Expression Property(this Expression expression, string propertyName) { // Todo:左边条件如果是dynamic, // 则Expression.Property无法获取子内容 // 报错在这里,由于expression内的对象为Object,所以无法解析到 // var x = (expression as IQueryable).ElementType; return Expression.Property(expression, propertyName); } /// <summary> /// 转Lambda /// </summary> public static Expression<TDelegate> ToLambda<TDelegate>(this Expression body, params ParameterExpression[] parameters) { return Expression.Lambda<TDelegate>(body, parameters); } #endregion #region 常用运算符 [ > , >= , == , < , <= , != , || , && ] /// <summary> /// && /// </summary> public static Expression AndAlso(this Expression left, Expression right) { return Expression.AndAlso(left, right); } /// <summary> /// || /// </summary> public static Expression OrElse(this Expression left, Expression right) { return Expression.OrElse(left, right); } /// <summary> /// Contains /// </summary> public static Expression Contains(this Expression left, Expression right) { return left.Call("Contains", right); } /// <summary> /// > /// </summary> public static Expression GreaterThan(this Expression left, Expression right) { return Expression.GreaterThan(left, right); } /// <summary> /// >= /// </summary> public static Expression GreaterThanOrEqual(this Expression left, Expression right) { return Expression.GreaterThanOrEqual(left, right); } /// <summary> /// < /// </summary> public static Expression LessThan(this Expression left, Expression right) { return Expression.LessThan(left, right); } /// <summary> /// <= /// </summary> public static Expression LessThanOrEqual(this Expression left, Expression right) { return Expression.LessThanOrEqual(left, right); } /// <summary> /// == /// </summary> public static Expression Equal(this Expression left, Expression right) { return Expression.Equal(left, right); } /// <summary> /// != /// </summary> public static Expression NotEqual(this Expression left, Expression right) { return Expression.NotEqual(left, right); } #endregion } /// <summary> /// Queryable扩展 /// </summary> public static class QueryableExtensions { #region 自定义扩展Queryable /// <summary> /// Where扩展 /// </summary> public static IEnumerable<TSource> IWhere<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.Where(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary> /// FirstOrDefault扩展 /// </summary> public static TSource IFirstOrDefault<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.FirstOrDefault(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary> /// Count扩展 /// </summary> public static Int32 ICount<TSource>(this IEnumerable<TSource> source, string linqStr) { return source.Count(DynamicLinqFactory.CreateLambda<TSource>(linqStr).Compile()); } /// <summary> /// 自定义排序 /// </summary> public static IOrderedQueryable<TSource> ISort<TSource>(this IQueryable<TSource> source, string orderByProperty, bool asc) { string command = asc ? "OrderBy" : "OrderByDescending"; var type = typeof(TSource); var property = type.GetProperty(orderByProperty); var parameter = Expression.Parameter(type, "p"); var propertyAccess = Expression.MakeMemberAccess(parameter, property); var orderByExpression = Expression.Lambda(propertyAccess, parameter); var resultExpression = Expression.Call(typeof(Queryable), command, new Type[] { type, property.PropertyType }, source.Expression, Expression.Quote(orderByExpression)); return (IOrderedQueryable<TSource>)source.Provider.CreateQuery<TSource>(resultExpression); } /// <summary> /// 自定义分页 /// </summary> /// <typeparam name="TSource"></typeparam> /// <param name="source"></param> /// <param name="nowPage"></param> /// <param name="pageSize"></param> /// <returns></returns> public static IQueryable<TSource> IPaging<TSource>(this IQueryable<TSource> source, int nowPage, int pageSize) { return source.ISkip((nowPage - 1) * pageSize).ITake(pageSize); } /// <summary> /// 自定义Skip /// </summary> public static IQueryable<TSource> ISkip<TSource>(this IQueryable<TSource> source, int count) { return source.Provider.CreateQuery<TSource>(Expression.Call( // 类别 typeof(Queryable), // 调用的方法 "Skip", // 元素类别 new Type[] { source.ElementType }, // 调用的表达树 source.Expression, // 参数 Expression.Constant(count))); } /// <summary> /// 自定义Take /// </summary> public static IQueryable<TSource> ITake<TSource>(this IQueryable<TSource> source, int count) { return source.Provider.CreateQuery<TSource>(Expression.Call( // 类别 typeof(Queryable), // 调用的方法 "Take", // 元素类别 new Type[] { source.ElementType }, // 调用的表达树 source.Expression, // 参数 Expression.Constant(count))); } /// <summary> /// 自定义去重复 /// </summary> public static IEnumerable<TSource> IDistinctBy<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector) { var seenKeys = new HashSet<TKey>(); return source.Where(element => seenKeys.Add(keySelector(element))); } /// <summary> /// 动态赋值 /// </summary> public static void CopyTo<T>(this object source, T target) where T : class, new() { if (source == null) return; if (target == null) { target = new T(); } foreach (var property in target.GetType().GetProperties()) { // 这里可以判断一下当前属性值是否为空的 source.GetType().GetProperty(property.Name).GetValue(source, null) target.GetType().InvokeMember(property.Name, BindingFlags.SetProperty, null, target, new object[] { source.GetType().GetProperty(property.Name).GetValue(source, null) }); } } /// <summary> /// 移除特殊字段数据 /// </summary> public static void RemoveSpecialPropertyValue(this object source) { var properties = source.GetType().GetProperties(); foreach (var x in properties) { if (x.GetAccessors().Any(y => y.IsVirtual)) { source.GetType().GetProperty(x.Name).SetValue(source, null, null); } } } #endregion } }