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
}