using System; 
 | 
using System.Collections.Generic; 
 | 
using System.Linq; 
 | 
using System.Linq.Expressions; 
 | 
using System.Reflection; 
 | 
using System.Text; 
 | 
using System.Threading.Tasks; 
 | 
using WIDESEAWCS_Core.Enums; 
 | 
using WIDESEAWCS_Core.Helper; 
 | 
  
 | 
namespace WIDESEAWCS_Core.Utilities 
 | 
{ 
 | 
    public static class LambdaExtensions 
 | 
    { 
 | 
        /// <summary> 
 | 
        ///  
 | 
        /// </summary> 
 | 
        /// <typeparam name="T"></typeparam> 
 | 
        /// <param name="propertyName">字段名</param> 
 | 
        /// <param name="propertyValue">表达式的值</param> 
 | 
        /// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue  
 | 
        /// p=>p.propertyName.Contains(propertyValue)</param> 
 | 
        /// <returns></returns> 
 | 
        public static Expression<Func<T, bool>> CreateExpression<T>(this string propertyName, object propertyValue, LinqExpressionType expressionType) 
 | 
        { 
 | 
            return propertyName.CreateExpression<T>(propertyValue, null, expressionType); 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        ///  
 | 
        /// </summary> 
 | 
        /// <typeparam name="T"></typeparam> 
 | 
        /// <param name="propertyName">字段名</param> 
 | 
        /// <param name="propertyValue">表达式的值</param> 
 | 
        /// <param name="expressionType">创建表达式的类型,如:p=>p.propertyName != propertyValue  
 | 
        /// p=>p.propertyName.Contains(propertyValue)</param> 
 | 
        /// <returns></returns> 
 | 
        private static Expression<Func<T, bool>> CreateExpression<T>( 
 | 
          this string propertyName, 
 | 
          object propertyValue, 
 | 
          ParameterExpression parameter, 
 | 
          LinqExpressionType expressionType) 
 | 
        { 
 | 
            Type proType = null; 
 | 
            PropertyInfo propertyInfo = typeof(T).GetProperty(propertyName); 
 | 
            if (propertyInfo != null) 
 | 
                proType = propertyInfo.PropertyType; 
 | 
            else 
 | 
            { 
 | 
                propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToLower()); 
 | 
                if (propertyInfo != null) 
 | 
                    proType = propertyInfo.PropertyType; 
 | 
                else 
 | 
                { 
 | 
                    propertyInfo = typeof(T).GetProperty(propertyName.FirstLetterToUpper()); 
 | 
                    if (propertyInfo != null) 
 | 
                        proType = propertyInfo.PropertyType; 
 | 
                    else 
 | 
                    { 
 | 
                        throw new Exception($"未找到该属性,type:{typeof(T)}"); 
 | 
                    } 
 | 
                } 
 | 
            } 
 | 
            //创建节点变量如p=>的节点p 
 | 
            //  parameter ??= Expression.Parameter(typeof(T), "p");//创建参数p 
 | 
            parameter = parameter ?? Expression.Parameter(typeof(T), "p"); 
 | 
  
 | 
            //创建节点的属性p=>p.name 属性name 
 | 
            MemberExpression memberProperty = Expression.PropertyOrField(parameter, propertyName); 
 | 
            if (expressionType == LinqExpressionType.In) 
 | 
            { 
 | 
                if (!(propertyValue is System.Collections.IList list) || list.Count == 0) throw new Exception("属性值类型不正确"); 
 | 
  
 | 
                bool isStringValue = true; 
 | 
                List<object> objList = new List<object>(); 
 | 
  
 | 
                if (proType.ToString() != "System.String") 
 | 
                { 
 | 
                    isStringValue = false; 
 | 
                    foreach (var value in list) 
 | 
                    { 
 | 
                        objList.Add(value.ToString().ChangeType(proType)); 
 | 
                    } 
 | 
                    list = objList; 
 | 
                } 
 | 
  
 | 
                if (isStringValue) 
 | 
                { 
 | 
                    //string 类型的字段,如果值带有'单引号,EF会默认变成''两个单引号 
 | 
                    MethodInfo method = typeof(System.Collections.IList).GetMethod("Contains"); 
 | 
                    //创建集合常量并设置为常量的值 
 | 
                    ConstantExpression constantCollection = Expression.Constant(list); 
 | 
                    //创建一个表示调用带参数的方法的:new string[]{"1","a"}.Contains("a"); 
 | 
                    MethodCallExpression methodCall = Expression.Call(constantCollection, method, memberProperty); 
 | 
                    return Expression.Lambda<Func<T, bool>>(methodCall, parameter); 
 | 
                } 
 | 
                //非string字段,按上面方式处理报异常Null TypeMapping in Sql Tree 
 | 
                BinaryExpression body = null; 
 | 
                foreach (var value in list) 
 | 
                { 
 | 
                    ConstantExpression constantExpression = Expression.Constant(value); 
 | 
                    UnaryExpression unaryExpression = Expression.Convert(memberProperty, constantExpression.Type); 
 | 
  
 | 
                    body = body == null 
 | 
                        ? Expression.Equal(unaryExpression, constantExpression) 
 | 
                        : Expression.OrElse(body, Expression.Equal(unaryExpression, constantExpression)); 
 | 
                } 
 | 
                return Expression.Lambda<Func<T, bool>>(body, parameter); 
 | 
            } 
 | 
  
 | 
            //  object value = propertyValue; 
 | 
            ConstantExpression constant = proType.ToString() == "System.String" 
 | 
                ? Expression.Constant(propertyValue) : Expression.Constant(propertyValue.ToString().ChangeType(proType)); 
 | 
  
 | 
            // DateTime只选择了日期的时候自动在结束日期加一天,修复DateTime类型使用日期区间查询无法查询到结束日期的问题 
 | 
            if ((proType == typeof(DateTime) || proType == typeof(DateTime?)) && expressionType == LinqExpressionType.LessThanOrEqual && propertyValue.ToString().Length == 10) 
 | 
            { 
 | 
                constant = Expression.Constant(Convert.ToDateTime(propertyValue.ToString()).AddDays(1)); 
 | 
            } 
 | 
  
 | 
            UnaryExpression member = Expression.Convert(memberProperty, constant.Type); 
 | 
            Expression<Func<T, bool>> expression; 
 | 
            switch (expressionType) 
 | 
            { 
 | 
                //p=>p.propertyName == propertyValue 
 | 
                case LinqExpressionType.Equal: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.Equal(member, constant), parameter); 
 | 
                    break; 
 | 
                //p=>p.propertyName != propertyValue 
 | 
                case LinqExpressionType.NotEqual: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.NotEqual(member, constant), parameter); 
 | 
                    break; 
 | 
                //   p => p.propertyName > propertyValue 
 | 
                case LinqExpressionType.GreaterThan: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThan(member, constant), parameter); 
 | 
                    break; 
 | 
                //   p => p.propertyName < propertyValue 
 | 
                case LinqExpressionType.LessThan: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.LessThan(member, constant), parameter); 
 | 
                    break; 
 | 
                // p => p.propertyName >= propertyValue 
 | 
                case LinqExpressionType.ThanOrEqual: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.GreaterThanOrEqual(member, constant), parameter); 
 | 
                    break; 
 | 
                // p => p.propertyName <= propertyValue 
 | 
                case LinqExpressionType.LessThanOrEqual: 
 | 
                    expression = Expression.Lambda<Func<T, bool>>(Expression.LessThanOrEqual(member, constant), parameter); 
 | 
                    break; 
 | 
                //   p => p.propertyName.Contains(propertyValue) 
 | 
                // p => !p.propertyName.Contains(propertyValue) 
 | 
                case LinqExpressionType.Contains: 
 | 
                case LinqExpressionType.NotContains: 
 | 
                    MethodInfo method = typeof(string).GetMethod("Contains", new[] { typeof(string) }); 
 | 
                    constant = Expression.Constant(propertyValue, typeof(string)); 
 | 
                    if (expressionType == LinqExpressionType.Contains) 
 | 
                    { 
 | 
                        expression = Expression.Lambda<Func<T, bool>>(Expression.Call(member, method, constant), parameter); 
 | 
                    } 
 | 
                    else 
 | 
                    { 
 | 
                        expression = Expression.Lambda<Func<T, bool>>(Expression.Not(Expression.Call(member, method, constant)), parameter); 
 | 
                    } 
 | 
                    break; 
 | 
                default: 
 | 
                    // p => p.false 
 | 
                    expression = False<T>(); 
 | 
                    break; 
 | 
            } 
 | 
            return expression; 
 | 
        } 
 | 
  
 | 
        /// <summary> 
 | 
        /// 创建lambda表达式:p=>false 
 | 
        /// </summary> 
 | 
        /// <typeparam name="T"></typeparam> 
 | 
        /// <returns></returns> 
 | 
        public static Expression<Func<T, bool>> False<T>() 
 | 
        { 
 | 
  
 | 
            return p => false; 
 | 
        } 
 | 
    } 
 | 
} 
 |