|
- using System.Linq.Expressions;
- using HealthMonitor.Util.QueryObjects;
-
- namespace HealthMonitor.Core.Query
- {
- public class QueryExpressionParser<T>
- {
- private readonly ParameterExpression parameter;
-
- public QueryExpressionParser()
- {
- parameter = Expression.Parameter(typeof(T));
- }
-
- public Expression<Func<T, bool>> ParserConditions(IEnumerable<QueryFilterCondition> conditions)
- {
- try
- {
- //将条件转化成表达是的Body
- var query = ParseExpressionBody(conditions);
- return Expression.Lambda<Func<T, bool>>(query, parameter);
- }
- catch (Exception)
- {
- var query = Expression.Constant(false, typeof(bool));
- return Expression.Lambda<Func<T, bool>>(query, parameter);
- }
- }
-
- private Expression ParseExpressionBody(IEnumerable<QueryFilterCondition> 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;
- }
- }
- }
|