123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Linq.Expressions;
- using System.Reflection;
- namespace YBEE.EQM.Core
- {
- /// <summary>
- /// 动态生成查询表达式
- /// </summary>
- public static class LambdaExpressionBuilder
- {
- private static Expression GetExpression(ParameterExpression parameter, Condition condition)
- {
- var propertyParam = Expression.Property(parameter, condition.Field);
- var propertyInfo = propertyParam.Member as PropertyInfo;
- if (propertyInfo == null)
- throw new MissingMemberException(nameof(Condition), condition.Field);
- //Support Nullable<>
- var realPropertyType = Nullable.GetUnderlyingType(propertyInfo.PropertyType) ?? propertyInfo.PropertyType;
- if (propertyInfo.PropertyType.IsGenericType &&
- propertyInfo.PropertyType.GetGenericTypeDefinition() == typeof(Nullable<>))
- propertyParam = Expression.Property(propertyParam, "Value");
- //Support IEnumerable && IEnumerable<T>
- if (condition.Op != QueryTypeEnum.StdIn && condition.Op != QueryTypeEnum.StdNotIn)
- {
- condition.Value = Convert.ChangeType(condition.Value, realPropertyType);
- }
- else
- {
- var typeOfValue = condition.Value.GetType();
- var typeOfList = typeof(IEnumerable<>).MakeGenericType(realPropertyType);
- if (typeOfValue.IsGenericType && typeOfList.IsAssignableFrom(typeOfValue))
- condition.Value = typeof(Enumerable)
- .GetMethod("ToArray", BindingFlags.Public | BindingFlags.Static)
- ?.MakeGenericMethod(realPropertyType)
- .Invoke(null, new[] { condition.Value });
- }
- var constantParam = Expression.Constant(condition.Value);
- switch (condition.Op)
- {
- case QueryTypeEnum.Equals:
- return Expression.Equal(propertyParam, constantParam);
- case QueryTypeEnum.NotEquals:
- return Expression.NotEqual(propertyParam, constantParam);
- case QueryTypeEnum.Contains:
- return Expression.Call(propertyParam, "Contains", null, constantParam);
- case QueryTypeEnum.NotContains:
- return Expression.Not(Expression.Call(propertyParam, "Contains", null, constantParam));
- case QueryTypeEnum.StartsWith:
- return Expression.Call(propertyParam, "StartsWith", null, constantParam);
- case QueryTypeEnum.EndsWith:
- return Expression.Call(propertyParam, "EndsWith", null, constantParam);
- case QueryTypeEnum.GreaterThan:
- return Expression.GreaterThan(propertyParam, constantParam);
- case QueryTypeEnum.GreaterThanOrEquals:
- return Expression.GreaterThanOrEqual(propertyParam, constantParam);
- case QueryTypeEnum.LessThan:
- return Expression.LessThan(propertyParam, constantParam);
- case QueryTypeEnum.LessThanOrEquals:
- return Expression.LessThanOrEqual(propertyParam, constantParam);
- case QueryTypeEnum.StdIn:
- return Expression.Call(typeof(Enumerable), "Contains", new[] { realPropertyType }, constantParam, propertyParam);
- case QueryTypeEnum.StdNotIn:
- return Expression.Not(Expression.Call(typeof(Enumerable), "Contains", new[] { realPropertyType }, constantParam, propertyParam));
- default:
- break;
- }
- return null;
- }
- private static Expression GetGroupExpression(ParameterExpression parameter, List<Condition> orConditions)
- {
- if (orConditions.Count == 0)
- return null;
- var exps = orConditions.Select(c => GetExpression(parameter, c)).ToList();
- return exps.Aggregate<Expression, Expression>(null, (left, right) =>
- left == null ? right : Expression.OrElse(left, right));
- }
- public static Expression<Func<T, bool>> BuildLambda<T>(IEnumerable<Condition> conditions)
- {
- if (conditions == null || !conditions.Any())
- return x => true;
- var parameter = Expression.Parameter(typeof(T), "x");
- //简单条件
- var simpleExps = conditions
- .ToList()
- .FindAll(c => string.IsNullOrEmpty(c.OrGroup))
- .Select(c => GetExpression(parameter, c))
- .ToList();
- //复杂条件
- var complexExps = conditions
- .ToList()
- .FindAll(c => !string.IsNullOrEmpty(c.OrGroup))
- .GroupBy(x => x.OrGroup)
- .Select(g => GetGroupExpression(parameter, g.ToList()))
- .ToList();
- var exp = simpleExps.Concat(complexExps).Aggregate<Expression, Expression>(null, (left, right) =>
- left == null ? right : Expression.AndAlso(left, right));
- return Expression.Lambda<Func<T, bool>>(exp, parameter);
- }
- public static Expression<Func<T, bool>> BuildAndAlsoLambda<T>(IEnumerable<Condition> conditions)
- {
- if (conditions == null || !conditions.Any())
- return x => true;
- var parameter = Expression.Parameter(typeof(T), "x");
- var simpleExps = conditions
- .ToList()
- .Select(c => GetExpression(parameter, c))
- .ToList();
- var exp = simpleExps.Aggregate<Expression, Expression>(null, (left, right) =>
- left == null ? right : Expression.AndAlso(left, right));
- return Expression.Lambda<Func<T, bool>>(exp, parameter);
- }
- public static Expression<Func<T, bool>> BuildOrElseLambda<T>(IEnumerable<Condition> conditions)
- {
- if (conditions == null || !conditions.Any())
- return x => true;
- var parameter = Expression.Parameter(typeof(T), "x");
- var simpleExps = conditions
- .ToList()
- .Select(c => GetExpression(parameter, c))
- .ToList();
- var exp = simpleExps.Aggregate<Expression, Expression>(null, (left, right) =>
- left == null ? right : Expression.OrElse(left, right));
- return Expression.Lambda<Func<T, bool>>(exp, parameter);
- }
- }
- /// <summary>
- /// 查询条件
- /// </summary>
- [Serializable]
- public class Condition
- {
- /// <summary>
- /// 字段名
- /// </summary>
- public string Field { get; set; }
- /// <summary>
- /// 操作符
- /// </summary>
- public QueryTypeEnum Op { get; set; }
- /// <summary>
- /// 字段值
- /// </summary>
- public object Value { get; set; }
- /// <summary>
- /// 分组名称
- /// </summary>
- public string OrGroup { get; set; }
- }
- }
|