using SqlSugar;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using HT.Cloud.Code;
namespace HT.Cloud.DataBase
{
public static partial class WaterQuery
{
#region Filter 拼接
///
/// 创建linq表达示的body部分
///
public static Expression GenerateBody(this ParameterExpression param, Filter filterObj)
{
PropertyInfo property = typeof(T).GetProperty(filterObj.Key);
Expression left = null; //组装左边
//组装右边
Expression right = null;
if (property != null)
{
left = Expression.Property(param, property);
if (property.PropertyType == typeof(int))
{
int i;
try
{
i = int.Parse(filterObj.Value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
int? i;
try
{
i = int.Parse(filterObj.Value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.Value) ? null : i, typeof(int?));
}
else if (property.PropertyType == typeof(DateTime))
{
DateTime i;
try
{
i = DateTime.Parse(filterObj.Value);
}
catch (Exception)
{
i = DateTime.Now.AddYears(-100);
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
DateTime? i;
try
{
i = DateTime.Parse(filterObj.Value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.Value) ? null : i, typeof(DateTime?));
}
else if (property.PropertyType == typeof(string))
{
right = Expression.Constant(filterObj.Value);
}
else if (property.PropertyType == typeof(decimal))
{
decimal i;
try
{
i = decimal.Parse(filterObj.Value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
decimal? i;
try
{
i = decimal.Parse(filterObj.Value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.Value) ? null : i, typeof(decimal?));
}
else if (property.PropertyType == typeof(float))
{
float i;
try
{
i = float.Parse(filterObj.Value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
float? i;
try
{
i = float.Parse(filterObj.Value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.Value) ? null : i, typeof(float?));
}
else if (property.PropertyType == typeof(bool))
{
bool i = false;
if (filterObj.Value.ToString().ToLower() == "1" || filterObj.Value.ToString().ToLower() == "true")
{
i = true;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
bool i = false;
if (filterObj.Value.ToString().ToLower() == "1" || filterObj.Value.ToString().ToLower() == "true")
{
i = true;
}
right = Expression.Constant(i, typeof(bool?));
}
else if (property.PropertyType == typeof(Guid))
{
Guid i;
try
{
i = Guid.Parse(filterObj.Value);
}
catch (Exception)
{
i = new Guid();
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Guid?))
{
Guid? i;
try
{
i = Guid.Parse(filterObj.Value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.Value) ? null : i, typeof(Guid?));
}
else
{
throw new Exception("暂不能解析该Key的类型");
}
}
else //如果左边不是属性,直接是值的情况
{
left = Expression.Constant(filterObj.Key);
right = Expression.Constant(filterObj.Value);
}
//c.XXX=="XXX"
Expression filter = Expression.Equal(left, right);
switch (filterObj.Contrast)
{
case "<=":
filter = Expression.LessThanOrEqual(left, right);
break;
case "<":
filter = Expression.LessThan(left, right);
break;
case ">":
filter = Expression.GreaterThan(left, right);
break;
case ">=":
filter = Expression.GreaterThanOrEqual(left, right);
break;
case "!=":
filter = Expression.NotEqual(left, right);
break;
case "contains":
filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(filterObj.Value));
break;
case "in":
var lExp = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var methodInfo = typeof(List).GetMethod("Contains",
new Type[] { typeof(string) }); //Contains语句
filter = Expression.Call(lExp, methodInfo, left);
break;
case "not in":
var listExpression = Expression.Constant(filterObj.Value.Split(',').ToList()); //数组
var method = typeof(List).GetMethod("Contains", new Type[] { typeof(string) }); //Contains语句
filter = Expression.Not(Expression.Call(listExpression, method, left));
break;
//交集,使用交集时左值必须时固定的值
case "intersect": //交集
if (property != null)
{
throw new Exception("交集模式下,表达式左边不能为变量,请调整数据规则,如:c=>\"A,B,C\" intersect \"B,D\"");
}
var rightval = filterObj.Value.Split(',').ToList();
var leftval = filterObj.Key.Split(',').ToList();
var val = rightval.Intersect(leftval);
filter = Expression.Constant(val.Any());
break;
}
return filter;
}
public static Expression> GenerateTypeBody(this ParameterExpression param, Filter filterObj)
{
return (Expression>)(param.GenerateBody(filterObj));
}
///
/// 转换FilterGroup为Lambda表达式
///
///
///
///
///
///
public static ISugarQueryable GenerateFilter(this ISugarQueryable query, string parametername,
List filterList)
{
var param = ExtLinq.CreateLambdaParam(parametername);
Expression result = ConvertList(filterList, param);
query = query.Where(param.GenerateTypeLambda(result));
return query;
}
///
/// 转换filterlist为表达式
///
///
///
///
///
public static Expression ConvertList(List filterList, ParameterExpression param)
{
if (filterList == null) return null;
Expression result = ConvertFilters(JsonHelper.ToObject(filterList[0].Filters), param, filterList[0].Operation);
foreach (var item in filterList.Skip(1))
{
var gresult = ConvertFilters(JsonHelper.ToObject(item.Filters), param, item.Operation);
result = result.OrElse(gresult);
}
return result;
}
///
/// 转换Filter数组为表达式
///
///
///
///
///
///
private static Expression ConvertFilters(Filter[] filters, ParameterExpression param, string operation)
{
if (filters == null || !filters.Any())
{
return null;
}
Expression result = param.GenerateBody(filters[0]);
if (filters.Length == 1)
{
return result;
}
if (operation == "and")
{
foreach (var filter in filters.Skip(1))
{
result = result.AndAlso(param.GenerateBody(filter));
}
}
else
{
foreach (var filter in filters.Skip(1))
{
result = result.OrElse(param.GenerateBody(filter));
}
}
return result;
}
#endregion Filter 拼接
#region SoulPage 拼接
///
/// 创建linq表达示的body部分
///
public static Expression GenerateBody(this ParameterExpression param, FilterSo filterObj)
{
PropertyInfo property = typeof(T).GetProperty(filterObj.field);
Expression left = null; //组装左边
//组装右边
Expression right = null;
if (property != null)
{
left = Expression.Property(param, property);
if (property.PropertyType == typeof(int))
{
int i;
try
{
i = int.Parse(filterObj.value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
int? i;
try
{
i = int.Parse(filterObj.value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.value) ? null : i, typeof(int?));
}
else if (property.PropertyType == typeof(DateTime))
{
DateTime i;
try
{
i = DateTime.Parse(filterObj.value);
}
catch (Exception)
{
i = DateTime.Now.AddYears(-100);
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
DateTime? i;
try
{
i = DateTime.Parse(filterObj.value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.value) ? null : i, typeof(DateTime?));
}
else if (property.PropertyType == typeof(string))
{
right = Expression.Constant(filterObj.value);
}
else if (property.PropertyType == typeof(decimal))
{
decimal i;
try
{
i = decimal.Parse(filterObj.value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
decimal? i;
try
{
i = decimal.Parse(filterObj.value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.value) ? null : i, typeof(decimal?));
}
else if (property.PropertyType == typeof(float))
{
float i;
try
{
i = float.Parse(filterObj.value);
}
catch (Exception)
{
i = -99999;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
float? i;
try
{
i = float.Parse(filterObj.value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.value) ? null : i, typeof(float?));
}
else if (property.PropertyType == typeof(bool))
{
bool i = false;
if (filterObj.value.ToString().ToLower() == "1" || filterObj.value.ToString().ToLower() == "true")
{
i = true;
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Nullable))
{
bool i = false;
if (filterObj.value.ToString().ToLower() == "1" || filterObj.value.ToString().ToLower() == "true")
{
i = true;
}
right = Expression.Constant(i, typeof(bool?));
}
else if (property.PropertyType == typeof(Guid))
{
Guid i;
try
{
i = Guid.Parse(filterObj.value);
}
catch (Exception)
{
i = new Guid();
}
right = Expression.Constant(i);
}
else if (property.PropertyType == typeof(Guid?))
{
Guid? i;
try
{
i = Guid.Parse(filterObj.value);
}
catch (Exception)
{
i = null;
}
right = Expression.Constant(string.IsNullOrEmpty(filterObj.value) ? null : i, typeof(Guid?));
}
else
{
throw new Exception("暂不能解析该Key的类型");
}
}
else //如果左边不是属性,直接是值的情况
{
throw new Exception("暂不能解析该Key的类型");
}
Expression filter = Expression.Equal(left, right);
switch (filterObj.type)
{
case "eq":
filter = Expression.Equal(left, right);
break;
case "ne":
filter = Expression.NotEqual(left, right);
break;
case "gt":
try
{
filter = Expression.GreaterThan(left, right);
}
catch (Exception)
{
filter = Expression.NotEqual(left, right);
}
break;
case "ge":
try
{
filter = Expression.GreaterThanOrEqual(left, right);
}
catch (Exception)
{
filter = Expression.Equal(left, right);
}
break;
case "lt":
try
{
filter = Expression.LessThan(left, right);
}
catch (Exception)
{
filter = Expression.NotEqual(left, right);
}
break;
case "le":
try
{
filter = Expression.LessThanOrEqual(left, right);
}
catch (Exception)
{
filter = Expression.Equal(left, right);
}
break;
case "contain":
try
{
filter = Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(filterObj.value));
}
catch (Exception)
{
filter = Expression.Equal(left, right);
}
break;
case "notContain":
try
{
filter = Expression.Not(Expression.Call(left, typeof(string).GetMethod("Contains", new Type[] { typeof(string) }),
Expression.Constant(filterObj.value)));
}
catch (Exception)
{
filter = Expression.NotEqual(left, right);
}
break;
case "start":
try
{
filter = Expression.Call(left, typeof(string).GetMethod("StartsWith", new Type[] { typeof(string) }),
Expression.Constant(filterObj.value));
}
catch (Exception)
{
filter = Expression.Equal(left, right);
}
break;
case "end":
try
{
filter = Expression.Call(left, typeof(string).GetMethod("EndsWith", new Type[] { typeof(string) }),
Expression.Constant(filterObj.value));
}
catch (Exception)
{
filter = Expression.Equal(left, right);
}
break;
case "null":
filter = Expression.Equal(left, Expression.Constant(null));
break;
case "notNull":
filter = Expression.NotEqual(left, Expression.Constant(null));
break;
default: break;
}
return filter;
}
///
/// 转换FilterGroup为Lambda表达式
///
///
///
///
///
///
public static ISugarQueryable GenerateFilter(this ISugarQueryable query, string parametername,
List filterList)
{
var param = ExtLinq.CreateLambdaParam(parametername);
Expression result = ConvertList(filterList, param);
if (result == null)
{
return query;
}
query = query.Where(param.GenerateTypeLambda(result));
return query;
}
///
/// 转换filterlist为表达式
///
///
///
///
///
public static Expression ConvertList(List filterList, ParameterExpression param)
{
if (filterList == null) return null;
Expression result = null;
Expression gresult = null;
PropertyInfo property;
Expression left = null;
foreach (var item in filterList)
{
switch (item.mode)
{
case "condition":
gresult = param.GenerateBody(item);
if (gresult == null)
{
break;
}
if (item.prefix == "or")
{
if (result != null)
{
result = result.OrElse(gresult);
}
else
{
result = gresult;
}
}
else
{
if (result != null)
{
result = result.AndAlso(gresult);
}
else
{
result = gresult;
}
}
break;
case "group":
gresult = ConvertList(item.children, param);
if (gresult == null)
{
break;
}
if (item.prefix == "or")
{
if (result != null)
{
result = result.OrElse(gresult);
}
else
{
result = gresult;
}
}
else
{
if (result != null)
{
result = result.AndAlso(gresult);
}
else
{
result = gresult;
}
}
break;
case "in":
property = typeof(T).GetProperty(item.field);
left = Expression.Property(param, property);
if (item.values == null || item.values.Count == 0)
{
break;
}
if (property.PropertyType == typeof(int))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(int.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(int) }), left);
}
if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(int.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(int?) }), left);
}
else if (property.PropertyType == typeof(DateTime))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(DateTime.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(DateTime) }), left);
}
else if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(DateTime.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(DateTime?) }), left);
}
else if (property.PropertyType == typeof(decimal))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(decimal.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(decimal) }), left);
}
else if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(decimal.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(decimal?) }), left);
}
else if (property.PropertyType == typeof(bool))
{
List list = new List();
foreach (var temp in item.values)
{
if (temp == "1")
{
gresult = Expression.Equal(left, Expression.Constant(true));
}
else
{
if (gresult == null)
{
gresult = Expression.Equal(left, Expression.Constant(false));
}
else
{
gresult.OrElse(Expression.Equal(left, Expression.Constant(false)));
}
}
}
}
else if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
if (temp == "1")
{
gresult = Expression.Equal(left, Expression.Constant(true, typeof(bool?)));
}
else
{
if (gresult == null)
{
gresult = Expression.Equal(left, Expression.Constant(false, typeof(bool?)));
}
else
{
gresult.OrElse(Expression.Equal(left, Expression.Constant(false, typeof(bool?))));
}
}
}
}
else if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(float.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(float?) }), left);
}
else if (property.PropertyType == typeof(float))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(float.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(float) }), left);
}
else if (property.PropertyType == typeof(Nullable))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(float.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(double?) }), left);
}
else if (property.PropertyType == typeof(double))
{
List list = new List();
foreach (var temp in item.values)
{
list.Add(float.Parse(temp));
}
gresult = Expression.Call(Expression.Constant(list), typeof(List).GetMethod("Contains", new Type[] { typeof(double) }), left);
}
else
{
gresult = Expression.Call(Expression.Constant(item.values), typeof(List).GetMethod("Contains", new Type[] { typeof(string) }), left);
}
if (result != null)
{
result = result.AndAlso(gresult);
}
else
{
result = gresult;
}
break;
case "date":
property = typeof(T).GetProperty(item.field);
left = Expression.Property(param, property);
bool isNull = false;
if (property.PropertyType == typeof(Nullable))
{
isNull = true;
}
DateTime? startTime = null;
DateTime? endTime = null;
switch (item.type)
{
case "yesterday":
startTime = DateTime.Now.Date.AddDays(-1);
endTime = DateTime.Now.Date;
break;
case "thisWeek":
startTime = DateTime.Now.Date.AddDays(1 - Convert.ToInt32(DateTime.Now.Date.DayOfWeek.ToString("d"))); //本周周一
endTime = ((DateTime)startTime).AddDays(7); //本周周日
break;
case "lastWeek":
startTime = DateTime.Now.Date.AddDays(1 - Convert.ToInt32(DateTime.Now.Date.DayOfWeek.ToString("d")) - 7); //上周周一
endTime = ((DateTime)startTime).AddDays(7); //上周周日
break;
case "thisMonth":
startTime = DateTime.Now.Date.AddDays(1 - DateTime.Now.Date.Day); //本月月初
endTime = ((DateTime)startTime).AddMonths(1); //本月月末
break;
case "thisYear":
startTime = new DateTime(DateTime.Now.Date.Year, 1, 1); //本年年初
endTime = new DateTime(DateTime.Now.Date.AddYears(1).Year, 1, 1); //本年年初
break;
case "specific":
var tempTime = item.value.Split('~');
if (tempTime.Length == 0 || tempTime.Length == 1)
{
var A = DateTime.Parse(tempTime[0]);
startTime = A.Date;
endTime = A.Date.AddDays(+1);
}
else
{
startTime = DateTime.Parse(tempTime[0]);
endTime = DateTime.Parse(tempTime[1]);
}
break;
default: break;
}
if (startTime != null && endTime != null)
{
if (isNull)
{
gresult = Expression.GreaterThanOrEqual(left, Expression.Constant(startTime, typeof(DateTime?)));
gresult = gresult.AndAlso(Expression.LessThan(left, Expression.Constant(endTime, typeof(DateTime?))));
}
else
{
gresult = Expression.GreaterThanOrEqual(left, Expression.Constant((DateTime)startTime));
gresult = gresult.AndAlso(Expression.LessThan(left, Expression.Constant((DateTime)endTime)));
}
}
if (result != null)
{
result = result.AndAlso(gresult);
}
else
{
result = gresult;
}
break;
default:
break;
}
}
return result;
}
#endregion SoulPage 拼接
}
}