using System.Collections; using System.Linq.Expressions; using System.Reflection; namespace VberZero.Tools.Lambda; public static class LambdaHelper { /// /// 创建主键为Id的查询表达式 /// /// /// /// /// public static Expression> CreatePrimaryKeyExp(TPrimaryKey id) { ParameterExpression left = Expression.Parameter(typeof(TEntity), "a"); MemberExpression member = Expression.PropertyOrField(left, "Id"); ConstantExpression constant = Expression.Constant(id, typeof(TPrimaryKey)); Expression right = Expression.Equal(member, constant); Expression> exp = Expression.Lambda>(right, left); return exp; } /// /// 创建某字段的查询表达式 /// /// /// /// /// public static Expression> CreateFieldExp(string name, object value) { ParameterExpression left = Expression.Parameter(typeof(TEntity), "a"); MemberExpression member = Expression.PropertyOrField(left, name); ConstantExpression constant = Expression.Constant(value, typeof(TEntity).GetProperty(name)?.PropertyType ?? throw new InvalidOperationException()); Expression right = Expression.Equal(member, constant); Expression> exp = Expression.Lambda>(right, left); return exp; } #region ORDER BY /// /// 创建lambda表达式:p=>p.propertyName /// /// /// /// /// public static Expression> GetOrderExp(string propertyName) { ParameterExpression parameter = Expression.Parameter(typeof(T), "o"); return Expression.Lambda>(Expression.Property(parameter, propertyName), parameter); } #endregion ORDER BY #region WHERE /// /// 创建 LambdaExpression> /// /// /// /// /// public static Expression> GetExp(this LambdaObject obj, ParameterExpression left = null) { Expression> finalExp = null; left = left ?? Expression.Parameter(typeof(T), "a"); Expression right = GetRightExp(obj, left); if (right != null) finalExp = Expression.Lambda>(right, left); return finalExp; } /// /// 创建 LambdaExpression> /// /// /// /// /// public static Expression> GetExp(this List objs, ParameterExpression left = null) { Expression> finalExp = null; left = left ?? Expression.Parameter(typeof(T), "a"); Expression right = null; foreach (var obj in objs) { Expression exp = GetRightExp(obj, left); right = right == null ? exp : CombineExp(right, exp, obj.LogicType); } if (right != null) finalExp = Expression.Lambda>(right, left); return finalExp; } /// /// 创建 MemberExpression /// /// /// /// /// public static Expression GetRightExp(LambdaObject obj, ParameterExpression left) { left = left ?? Expression.Parameter(typeof(T), "a");//创建参数a string fieldName = obj.FieldName; //var fieldValue = obj.FieldValue; MemberExpression member = Expression.PropertyOrField(left, fieldName); Expression right = null; if (obj.Children != null && obj.Children.Any()) right = GetRightExps(obj.Children, left); else { Type t = typeof(T).GetProperty(fieldName)?.PropertyType; if (t == null) { fieldName = fieldName.Substring(0, 1).ToUpper() + fieldName.Substring(1); t = typeof(T).GetProperty(fieldName)?.PropertyType; t = t ?? GetFiledType(obj.FieldType); } object value = null; if (obj.FieldValue != null) { try { var newType = CheckNullableAndConvertType(t); if (newType.IsEnum) { value = Enum.ToObject(newType, Convert.ToInt32(obj.FieldValue)); } else { value = Convert.ChangeType(obj.FieldValue, newType); } } catch { return null; } } ConstantExpression constant = Expression.Constant(value, t); //var type = typeof(T).GetProperty(fieldName) ?? throw new InvalidOperationException(); //ConstantExpression constant = Expression.Constant(obj.FieldValue); switch ((int)obj.ExpType) { case 0: right = constant != null ? Expression.Equal(member, constant) : null; break; case 1: right = constant != null ? Expression.NotEqual(member, constant) : null; break; case 2: right = constant != null ? Expression.GreaterThan(member, constant) : null; break; case 3: right = constant != null ? Expression.LessThan(member, constant) : null; break; case 4: right = constant != null ? Expression.GreaterThanOrEqual(member, constant) : null; break; case 5: right = constant != null ? Expression.LessThanOrEqual(member, constant) : null; break; case 6: right = GetRightExp_Contains(obj, left); break; case 7: right = GetRightExp_NotContains(obj, left); break; case 8: break; } } return right; } /// /// 创建 MemberExpression /// /// /// /// /// public static Expression GetRightExps(List objs, ParameterExpression left) { left = left ?? Expression.Parameter(typeof(T), "a");//创建参数a Expression right = null; foreach (var obj in objs) { Expression exp = GetRightExp(obj, left); right = right == null ? exp : CombineExp(right, exp, obj.LogicType); } return right; } /// /// 创建 ConstantExpression /// private static ConstantExpression GetConstantExp(LambdaObject obj) { var fieldValue = obj.FieldValue; //Type t = GetFiledType(obj.FieldType); ConstantExpression constant = null; // Expression.Constant(fieldValue, t);; switch ((int)obj.FieldType) { case 0: constant = Expression.Constant(fieldValue is string ? fieldValue : fieldValue.ToString(), typeof(string)); break; case 1: if (fieldValue is int) constant = Expression.Constant(fieldValue, typeof(int)); else if (int.TryParse(fieldValue.ToString(), out int newValue)) constant = Expression.Constant(newValue, typeof(int)); break; case 2: if (fieldValue is int) constant = Expression.Constant(fieldValue, typeof(int?)); else if (int.TryParse(fieldValue.ToString(), out int newValue)) constant = Expression.Constant(newValue, typeof(int?)); break; case 3: if (fieldValue is bool) constant = Expression.Constant(fieldValue, typeof(bool)); else if (bool.TryParse(fieldValue.ToString(), out bool newValue)) constant = Expression.Constant(newValue, typeof(bool)); break; case 4: if (fieldValue is bool) constant = Expression.Constant(fieldValue, typeof(bool?)); else if (bool.TryParse(fieldValue.ToString(), out bool newValue)) constant = Expression.Constant(newValue, typeof(bool?)); break; case 5: if (fieldValue is DateTime) constant = Expression.Constant(fieldValue, typeof(DateTime)); else if (DateTime.TryParse(fieldValue.ToString(), out DateTime newValue)) constant = Expression.Constant(newValue, typeof(DateTime)); break; case 6: if (fieldValue is DateTime) constant = Expression.Constant(fieldValue, typeof(DateTime?)); else if (DateTime.TryParse(fieldValue.ToString(), out DateTime newValue)) constant = Expression.Constant(newValue, typeof(DateTime?)); break; case 7: if (fieldValue is long) constant = Expression.Constant(fieldValue, typeof(long)); else if (long.TryParse(fieldValue.ToString(), out long newValue)) constant = Expression.Constant(newValue, typeof(long)); break; case 8: if (fieldValue is long) constant = Expression.Constant(fieldValue, typeof(long?)); else if (long.TryParse(fieldValue.ToString(), out long newValue)) constant = Expression.Constant(newValue, typeof(long?)); break; case 9: if (fieldValue is short) constant = Expression.Constant(fieldValue, typeof(short)); else if (short.TryParse(fieldValue.ToString(), out short newValue)) constant = Expression.Constant(newValue, typeof(short)); break; case 10: if (fieldValue is short) constant = Expression.Constant(fieldValue, typeof(short?)); else if (short.TryParse(fieldValue.ToString(), out short newValue)) constant = Expression.Constant(newValue, typeof(short?)); break; case 11: if (fieldValue is float) constant = Expression.Constant(fieldValue, typeof(float)); else if (float.TryParse(fieldValue.ToString(), out float newValue)) constant = Expression.Constant(newValue, typeof(float)); break; case 12: if (fieldValue is float) constant = Expression.Constant(fieldValue, typeof(float?)); else if (float.TryParse(fieldValue.ToString(), out float newValue)) constant = Expression.Constant(newValue, typeof(float?)); break; case 13: if (fieldValue is decimal) constant = Expression.Constant(fieldValue, typeof(decimal)); else if (decimal.TryParse(fieldValue.ToString(), out decimal newValue)) constant = Expression.Constant(newValue, typeof(decimal)); break; case 14: if (fieldValue is decimal) constant = Expression.Constant(fieldValue, typeof(decimal?)); else if (decimal.TryParse(fieldValue.ToString(), out decimal newValue)) constant = Expression.Constant(newValue, typeof(decimal?)); break; case 15: if (fieldValue is double) constant = Expression.Constant(fieldValue, typeof(double)); else if (double.TryParse(fieldValue.ToString(), out double newValue)) constant = Expression.Constant(newValue, typeof(double)); break; case 16: if (fieldValue is double) constant = Expression.Constant(fieldValue, typeof(double?)); else if (double.TryParse(fieldValue.ToString(), out double newValue)) constant = Expression.Constant(newValue, typeof(double?)); break; } return constant; } private static Type CheckNullableAndConvertType(Type theType) { if (theType.IsGenericType && theType.GetGenericTypeDefinition() == typeof(Nullable<>)) { return theType.GetGenericArguments()[0]; } return theType; } private static Type GetFiledType(LambdaFieldType type) { switch (type) { case LambdaFieldType.S: return typeof(string); case LambdaFieldType.I: return typeof(int); case LambdaFieldType.Inull: return typeof(int?); case LambdaFieldType.B: return typeof(bool); case LambdaFieldType.Bnull: return typeof(bool?); case LambdaFieldType.D: return typeof(DateTime); case LambdaFieldType.Dnull: return typeof(DateTime?); case LambdaFieldType.L: return typeof(long); case LambdaFieldType.Lnull: return typeof(long?); case LambdaFieldType.Short: return typeof(short); case LambdaFieldType.Snull: return typeof(short?); case LambdaFieldType.F: return typeof(float); case LambdaFieldType.Fnull: return typeof(float?); case LambdaFieldType.Decimal: return typeof(decimal); case LambdaFieldType.DecimalNull: return typeof(decimal?); case LambdaFieldType.Double: return typeof(double); case LambdaFieldType.DoubleNull: return typeof(double?); default: return null; } } /// /// 创建lambda表达式:p=>p.propertyName.Contains(propertyValue) /// /// /// /// /// public static Expression GetRightExp_Contains(LambdaObject obj, ParameterExpression left = null) { string fieldName = obj.FieldName; var fieldValue = obj.FieldValue; left = left ?? Expression.Parameter(typeof(T), "a");//创建参数a MemberExpression member = Expression.PropertyOrField(left, fieldName); Expression right = null; switch (obj.FieldType) { case LambdaFieldType.S: var method1 = typeof(string).GetMethod("Contains", new[] { typeof(string) }); if (method1 == null) return null; if (fieldValue is string) { ConstantExpression constant = Expression.Constant(fieldValue.ToString());//创建常数 right = Expression.Call(member, method1, constant); } else { foreach (var o in (IEnumerable)fieldValue) { ConstantExpression constant = Expression.Constant(o); var temp = Expression.Call(member, method1, constant); right = right == null ? temp : CombineExp(right, temp, LogicType.Or); } } break; case LambdaFieldType.I: var method2 = typeof(int).GetMethod("Contains", new[] { typeof(int) }); if (method2 == null) return null; if (fieldValue is int) { ConstantExpression constant = Expression.Constant(fieldValue.ToString()); right = Expression.Call(member, method2, constant); } else { foreach (var o in (IEnumerable)fieldValue) { ConstantExpression constant = Expression.Constant(o); var temp = Expression.Call(member, method2, constant); right = right == null ? temp : CombineExp(right, temp, LogicType.Or); } } break; case LambdaFieldType.B: var method3 = typeof(bool).GetMethod("Contains", new[] { typeof(bool) }); if (method3 == null) return null; if (fieldValue is bool) { ConstantExpression constant = Expression.Constant(fieldValue.ToString()); right = Expression.Call(member, method3, constant); } break; } return right; } /// /// 创建lambda表达式:!(p=>p.propertyName.Contains(propertyValue)) /// /// /// /// /// public static Expression GetRightExp_NotContains(LambdaObject obj, ParameterExpression left = null) { return Expression.Not(GetRightExp_Contains(obj, left)); } /// /// 拼接 Expression /// /// /// /// /// public static Expression CombineExp(this Expression exp1, Expression exp2, LogicType type) { Expression exp = exp1; if (exp1 == null || exp2 == null) { return exp1; } switch ((int)type) { case 0: exp = Expression.And(exp1, exp2); break; case 1: exp = Expression.Or(exp1, exp2); break; } return exp; } #endregion WHERE #region 暂未用到 /// /// 创建 MemberExpression /// /// /// /// /// public static Expression GetRightExp2(List objs, ParameterExpression left) { Expression right = null; foreach (var obj in objs) { Expression exp = null; if (obj.Children.Any()) { exp = GetRightExps(obj.Children, left); right = right == null ? exp : CombineExp(right, exp, obj.LogicType); continue; } switch ((int)obj.ExpType) { case 0: exp = GetRightExp_Equal(obj, left); break; case 1: exp = GetRightExp_NotEqual(obj, left); break; case 2: break; case 3: break; case 4: break; case 5: break; case 6: break; case 7: exp = GetRightExp_Contains(obj); break; case 8: exp = GetRightExp_NotContains(obj); break; } right = right == null ? exp : CombineExp(right, exp, obj.LogicType); } return right; } /// /// 创建lambda表达式:p=>p.propertyName == propertyValue /// public static Expression GetRightExp_Equal(LambdaObject obj, ParameterExpression left = null) { //Expression> exp = null; string fieldName = obj.FieldName; var fieldValue = obj.FieldValue; left = left ?? Expression.Parameter(typeof(T), "a");//创建参数a MemberExpression member = Expression.PropertyOrField(left, fieldName); Expression right = null; switch ((int)obj.FieldType) { case 0: if (fieldValue is string) { ConstantExpression constant = Expression.Constant(fieldValue);//创建常数 //exp= Expression.Lambda>(Expression.Equal(member, constant), left); right = Expression.Equal(member, constant); } //else if (os is List) //{ // foreach (var o in (List) os) // { // ConstantExpression constant = Expression.Constant(o); // var temp = Expression.Equal(member, constant); // right = CombineExp(right,temp,obj.LogicType); // } //} break; case 1: if (fieldValue is int) { ConstantExpression constant = Expression.Constant(fieldValue); right = Expression.Equal(member, constant); } break; case 2: if (fieldValue is bool) { ConstantExpression constant = Expression.Constant(fieldValue); right = Expression.Equal(member, constant); } break; } return right; } /// /// 创建lambda表达式:p=>p.propertyName != propertyValue /// public static Expression GetRightExp_NotEqual(LambdaObject obj, ParameterExpression left = null) { string fieldName = obj.FieldName; var fieldValue = obj.FieldValue; left = left ?? Expression.Parameter(typeof(T), "a");//创建参数a MemberExpression member = Expression.PropertyOrField(left, fieldName); Expression right = null; switch ((int)obj.FieldType) { case 0: if (fieldValue is string) { ConstantExpression constant = Expression.Constant(fieldValue); right = Expression.NotEqual(member, constant); } break; case 1: if (fieldValue is int) { ConstantExpression constant = Expression.Constant(fieldValue); right = Expression.NotEqual(member, constant); } break; case 2: if (fieldValue is bool) { ConstantExpression constant = Expression.Constant(fieldValue); right = Expression.NotEqual(member, constant); } break; } return right; } /// /// 创建lambda表达式:p=>true /// /// /// public static Expression> True() { return p => true; } /// /// 创建lambda表达式:p=>false /// /// /// public static Expression> False() { return p => false; } /// /// 创建lambda表达式:p=>p.propertyName /// /// /// /// /// public static Expression> GetOrderExpression(string propertyName) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p"); return Expression.Lambda>(Expression.Property(parameter, propertyName), parameter); } /// /// 创建lambda表达式:p=>p.propertyName == propertyValue /// /// public static Expression> CreateEqual(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.Equal(member, constant), parameter); } /// /// 创建lambda表达式:p=>p.propertyName != propertyValue /// /// /// /// /// public static Expression> CreateNotEqual(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.NotEqual(member, constant), parameter); } /// /// 创建lambda表达式:p=>p.propertyName > propertyValue /// /// /// public static Expression> CreateGreaterThan(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.GreaterThan(member, constant), parameter); } /// /// 创建lambda表达式:p=>p.propertyName < propertyValue /> /// /// /// public static Expression> CreateLessThan(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.LessThan(member, constant), parameter); } /// /// 创建lambda表达式:p=>p.propertyName >= propertyValue /// /// /// public static Expression> CreateGreaterThanOrEqual(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.GreaterThanOrEqual(member, constant), parameter); } // ReSharper disable once InvalidXmlDocComment /// /// 创建lambda表达式:p=>p.propertyName <= propertyValue /// /// /// public static Expression> CreateLessThanOrEqual(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p");//创建参数p MemberExpression member = Expression.PropertyOrField(parameter, propertyName); ConstantExpression constant = Expression.Constant(propertyValue);//创建常数 return Expression.Lambda>(Expression.LessThanOrEqual(member, constant), parameter); } /// /// 创建lambda表达式:p=>p.propertyName.Contains(propertyValue) /// /// /// public static Expression> GetContains(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p"); MemberExpression member = Expression.PropertyOrField(parameter, propertyName); MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); ConstantExpression constant = Expression.Constant(propertyValue, typeof(string)); return Expression.Lambda>(Expression.Call(member, method ?? throw new InvalidOperationException(), constant), parameter); } /// /// 创建lambda表达式:!(p=>p.propertyName.Contains(propertyValue)) /// /// /// public static Expression> GetNotContains(string propertyName, string propertyValue) { ParameterExpression parameter = Expression.Parameter(typeof(T), "p"); MemberExpression member = Expression.PropertyOrField(parameter, propertyName); MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); ConstantExpression constant = Expression.Constant(propertyValue, typeof(string)); return Expression.Lambda>(Expression.Not(Expression.Call(member, method ?? throw new InvalidOperationException(), constant)), parameter); } #endregion 暂未用到 } public class LambdaObject { public LambdaObject() { } public LambdaObject(string fieldName, object fieldValue, LambdaExpType expType = LambdaExpType.Contains, LambdaFieldType fieldType = LambdaFieldType.S, LogicType logicType = LogicType.And) { FieldName = fieldName; FieldValue = fieldValue; FieldType = fieldType; ExpType = expType; LogicType = logicType; } public string FieldName { get; set; } public object FieldValue { get; set; } public LambdaFieldType FieldType { get; set; } public LambdaExpType ExpType { get; set; } public LogicType LogicType { get; set; } public List Children { get; set; } } /// /// 表达式类型 /// public enum LambdaExpType { Equal , NotEqual , Greater , Less , GreaterOrEqual , LessOrEqual , Contains , NotContains } /// /// 字段类型 /// public enum LambdaFieldType { /// /// string /// S = 0, /// /// int /// I = 1, /// /// int? /// Inull = 2, /// /// bool /// B = 3, /// /// bool? /// Bnull = 4, /// /// Datetime /// D = 5, /// /// Datetime? /// Dnull = 6, /// /// long /// L = 7, /// /// long? /// Lnull = 8, /// /// short /// Short = 9, /// /// Short? /// Snull = 10, /// /// float /// F = 11, /// /// float /// Fnull = 12, /// /// Decimal /// Decimal = 13, /// /// Decimal /// DecimalNull = 14, /// /// Double /// Double = 15, /// /// Double /// DoubleNull = 16 } /// /// 拼接时 AND || OR /// public enum LogicType { And, Or }