using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using System.Text; using System.Threading.Tasks; using WIDESEA_Core.Enums; using WIDESEA_Core.Helper; namespace WIDESEA_Core.Utilities { public static class LambdaExtensions { /// /// /// /// /// 字段名 /// 表达式的值 /// 创建表达式的类型,如:p=>p.propertyName != propertyValue /// p=>p.propertyName.Contains(propertyValue) /// public static Expression> CreateExpression(this string propertyName, object propertyValue, LinqExpressionType expressionType) { return propertyName.CreateExpression(propertyValue, null, expressionType); } /// /// /// /// /// 字段名 /// 表达式的值 /// 创建表达式的类型,如:p=>p.propertyName != propertyValue /// p=>p.propertyName.Contains(propertyValue) /// private static Expression> CreateExpression( this string propertyName, object propertyValue, ParameterExpression parameter, LinqExpressionType expressionType) { Type proType = null; PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName); if (propertyInfo != null) proType = propertyInfo.PropertyType; else { propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToLower()); if (propertyInfo != null) proType = propertyInfo.PropertyType; else { propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToUpper()); if (propertyInfo != null) proType = propertyInfo.PropertyType; else { throw new Exception($"未找到该属性,type:{typeof(T)}"); } } } //创建节点变量如p=>的节点p // parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p parameter = parameter ?? Expression.Parameter(typeof(T), "p"); //创建节点的属性p=>p.name 属性name MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName); if (expressionType == LinqExpressionType.In) { if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确"); bool isStringValue = true; List objList = new List(); if (proType.ToString() != "System.String") { isStringValue = false; foreach (var value in list) { objList.Add(value.ToString().ChangeType(proType)); } list = objList; } if (isStringValue) { //string 类型的字段,如果值带有'单引号,EF会默认变成''两个单引号 MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains"); //创建集合常量并设置为常量的值 ConstantExpression constantCollection = Expression.Constant(list); //创建一个表示调用带参数的方法的:new string[]{"1","a"}.Contains("a"); MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty); return Expression.Lambda>(methodCall, parameter); } //非string字段,按上面方式处理报异常Null TypeMapping in Sql Tree BinaryExpression body = null; foreach (var value in list) { ConstantExpression constantExpression = Expression.Constant(value); UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type); body = body == null ? Expression.Equal(unaryExpression, constantExpression) : Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression)); } return Expression.Lambda>(body, parameter); } // object value = propertyValue; ConstantExpression constant = proType.ToString() == "System.String" ? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType)); // DateTime只选择了日期的时候自动在结束日期加一天,修复DateTime类型使用日期区间查询无法查询到结束日期的问题 if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10) { constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1)); } UnaryExpression member = Expression.Convert(memberProperty, constant.Type); Expression> expression; switch (expressionType) { //p=>p.propertyName == propertyValue case LinqExpressionType.Equal: expression = Expression.Lambda>(Expression.Equal(member, constant), parameter); break; //p=>p.propertyName != propertyValue case LinqExpressionType.NotEqual: expression = Expression.Lambda>(Expression.NotEqual(member, constant), parameter); break; // p => p.propertyName > propertyValue case LinqExpressionType.GreaterThan: expression = Expression.Lambda>(Expression.GreaterThan(member, constant), parameter); break; // p => p.propertyName < propertyValue case LinqExpressionType.LessThan: expression = Expression.Lambda>(Expression.LessThan(member, constant), parameter); break; // p => p.propertyName >= propertyValue case LinqExpressionType.ThanOrEqual: expression = Expression.Lambda>(Expression.GreaterThanOrEqual(member, constant), parameter); break; // p => p.propertyName <= propertyValue case LinqExpressionType.LessThanOrEqual: expression = Expression.Lambda>(Expression.LessThanOrEqual(member, constant), parameter); break; // p => p.propertyName.Contains(propertyValue) // p => !p.propertyName.Contains(propertyValue) case LinqExpressionType.Contains: case LinqExpressionType.NotContains: MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); constant = Expression.Constant(propertyValue, typeof(string)); if (expressionType == LinqExpressionType.Contains) { expression = Expression.Lambda>(Expression.Call(member, method, constant), parameter); } else { expression = Expression.Lambda>(Expression.Not(Expression.Call(member, method, constant)), parameter); } break; default: // p => p.false expression = False(); break; } return expression; } /// /// 创建lambda表达式:p=>false /// /// /// public static Expression> False() { return p => false; } public static Expression> GetWhereExpression(this PropertyInfo propertyInfo, object propertyValue, ParameterExpression parameter, LinqExpressionType expressionType) { Type proType = propertyInfo.PropertyType; ConstantExpression constant = proType.ToString() == "System.String" ? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType)); // DateTime只选择了日期的时候自动在结束日期加一天,修复DateTime类型使用日期区间查询无法查询到结束日期的问题 if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10) { constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1)); } parameter = parameter ?? Expression.Parameter(typeof(TEntity), "b"); //创建节点的属性p=>p.name 属性name MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyInfo.Name); UnaryExpression member = Expression.Convert(memberProperty, constant.Type); Expression> expression = p => false; switch (expressionType) { //p=>p.propertyName == propertyValue case LinqExpressionType.Equal: expression = Expression.Lambda>(Expression.Equal(member, constant), parameter); break; //p=>p.propertyName != propertyValue case LinqExpressionType.NotEqual: expression = Expression.Lambda>(Expression.NotEqual(member, constant), parameter); break; // p => p.propertyName > propertyValue case LinqExpressionType.GreaterThan: expression = Expression.Lambda>(Expression.GreaterThan(member, constant), parameter); break; // p => p.propertyName < propertyValue case LinqExpressionType.LessThan: expression = Expression.Lambda>(Expression.LessThan(member, constant), parameter); break; // p => p.propertyName >= propertyValue case LinqExpressionType.ThanOrEqual: expression = Expression.Lambda>(Expression.GreaterThanOrEqual(member, constant), parameter); break; // p => p.propertyName <= propertyValue case LinqExpressionType.LessThanOrEqual: expression = Expression.Lambda>(Expression.LessThanOrEqual(member, constant), parameter); break; // p => p.propertyName.Contains(propertyValue) // p => !p.propertyName.Contains(propertyValue) case LinqExpressionType.Contains: case LinqExpressionType.NotContains: MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); constant = Expression.Constant(propertyValue, typeof(string)); if (expressionType == LinqExpressionType.Contains) { expression = Expression.Lambda>(Expression.Call(member, method, constant), parameter); } else { expression = Expression.Lambda>(Expression.Not(Expression.Call(member, method, constant)), parameter); } break; default: // expression = p => false; break; } return expression; } } }