using System.Linq.Expressions; using HealthMonitor.Util.QueryObjects; namespace HealthMonitor.Core.Query { public class QueryExpressionParser { private readonly ParameterExpression parameter; public QueryExpressionParser() { parameter = Expression.Parameter(typeof(T)); } public Expression> ParserConditions(IEnumerable conditions) { try { //将条件转化成表达是的Body var query = ParseExpressionBody(conditions); return Expression.Lambda>(query, parameter); } catch (Exception) { var query = Expression.Constant(false, typeof(bool)); return Expression.Lambda>(query, parameter); } } private Expression ParseExpressionBody(IEnumerable conditions) { if (conditions == null || conditions.Count() == 0) { return Expression.Constant(true, typeof(bool)); } else if (conditions.Count() == 1) { return ParseCondition(conditions.First()); } else { Expression left = ParseCondition(conditions.First()); Expression right = ParseExpressionBody(conditions.Skip(1)); return Expression.AndAlso(left, right); } } private Expression GetValueExpression(QueryFilterCondition condition) { string[]? array = null; switch (condition.Operator) { case QueryOperatorEnum.In: case QueryOperatorEnum.Between: array = condition.Value!.Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); break; } switch (condition.ValueType) { case QueryValueTypeEnum.Int: case QueryValueTypeEnum.Long: { long data; if (array != null) { return Expression.NewArrayInit(typeof(long), array.Select(e => Expression.Constant(long.TryParse(e, out data) ? data : 0))); } return Expression.Constant(long.TryParse(condition.Value, out data) ? data : 0); } case QueryValueTypeEnum.Float: case QueryValueTypeEnum.Double: case QueryValueTypeEnum.Decimal: { double data; if (array != null) { return Expression.NewArrayInit(typeof(double), array.Select(e => Expression.Constant(double.TryParse(e, out data) ? data : 0))); } return Expression.Constant(double.TryParse(condition.Value, out data) ? data : 0); } case QueryValueTypeEnum.DateTime: { DateTime data; if (array != null) { return Expression.NewArrayInit(typeof(DateTime), array.Select(e => Expression.Constant(DateTime.TryParse(e, out data) ? data : DateTime.Now))); } return Expression.Constant(DateTime.TryParse(condition.Value, out data) ? data : DateTime.Now); } case QueryValueTypeEnum.Boolean: { return Expression.Constant(bool.TryParse(condition.Value, out bool data) ? data : false); } default: { if (array != null) { return Expression.NewArrayInit(typeof(string), array.Select(e => Expression.Constant(e))); } return Expression.Constant(condition.Value); } } } private Expression ParseCondition(QueryFilterCondition condition) { ParameterExpression p = parameter; Expression key = Expression.Property(p, condition.Key!); Expression value = GetValueExpression(condition); switch (condition.Operator) { case QueryOperatorEnum.Contains: return Expression.Call(key, typeof(string).GetMethod("Contains", new Type[] { typeof(string) })!, value); case QueryOperatorEnum.Equal: return Expression.Equal(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.Greater: return Expression.GreaterThan(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.GreaterEqual: return Expression.GreaterThanOrEqual(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.Less: return Expression.LessThan(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.LessEqual: return Expression.LessThanOrEqual(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.NotEqual: return Expression.NotEqual(key, Expression.Convert(value, key.Type)); case QueryOperatorEnum.In: return ParaseIn(p, condition, (value as NewArrayExpression)!); case QueryOperatorEnum.Between: return ParaseBetween(p, condition); default: throw new NotImplementedException("不支持此操作"); } } private Expression ParaseBetween(ParameterExpression parameter, QueryFilterCondition conditions) { ParameterExpression p = parameter; Expression key = Expression.Property(p, conditions.Key!); var valueArr = conditions?.Value?.Split(','); if (valueArr!.Length != 2) { throw new NotImplementedException("ParaseBetween参数错误"); } double startValue = 0, endValue = 0; try { startValue = double.Parse(valueArr[0]); endValue = double.Parse(valueArr[1]); } catch { throw new NotImplementedException("ParaseBetween参数只能为数字"); } if (startValue >= endValue) throw new ArgumentOutOfRangeException("ParaseBetween参数起始值和终止值错误"); Expression expression = Expression.Constant(true, typeof(bool)); //开始位置 Expression startvalue = Expression.Constant(startValue); Expression start = Expression.GreaterThanOrEqual(key, Expression.Convert(startvalue, key.Type)); Expression endvalue = Expression.Constant(endValue); Expression end = Expression.LessThanOrEqual(key, Expression.Convert(endvalue, key.Type)); return Expression.AndAlso(start, end); } private Expression ParaseIn(ParameterExpression parameter, QueryFilterCondition conditions, NewArrayExpression values) { ParameterExpression p = parameter; Expression key = Expression.Property(p, conditions.Key!); Expression expression = Expression.Constant(false, typeof(bool)); foreach (var value in values.Expressions) { Expression right = Expression.Equal(key, Expression.Convert(value, key.Type)); expression = Expression.Or(expression, right); } //var valueArr = conditions.Value.Split(','); //foreach (var itemVal in valueArr) //{ // Expression value = Expression.Constant(itemVal); // Expression right = Expression.Equal(key, Expression.Convert(value, key.Type)); // expression = Expression.Or(expression, right); //} return expression; } } }