public Expression <Func <T, bool> > AsExpression <T>() where T : class
        {
            QueryCollection queryCollection = new QueryCollection();
            var             properties      = typeof(T).GetTypeInfo().GetProperties();

            if (Columns == null)
            {
                return(t => true);
            }
            foreach (var item in Columns)
            {
                var p = properties.FirstOrDefault(m => m.Name.Equals(item.Name, StringComparison.OrdinalIgnoreCase));
                if (p == null)
                {
                    continue;
                }
                var    realType = Nullable.GetUnderlyingType(p.PropertyType) ?? p.PropertyType;
                string value    = null;
                if (item.Search != null && item.Search.Value.IsNotNullAndWhiteSpace())
                {
                    value = item.Search.Value;
                }
                else if (Search != null && Search.Value.IsNotNullAndWhiteSpace() && realType == typeof(string))
                {
                    value = Search.Value;
                }
                if ((item.Search.Opeartor == Query.Operators.Range && item.Search.ValueMin.IsNullOrWhiteSpace() && item.Search.ValueMax.IsNullOrWhiteSpace()) ||
                    (item.Search.Opeartor != Query.Operators.Range && value.IsNullOrWhiteSpace()))
                {
                    continue;
                }

                Query query = new Query();
                query.Name = p.Name;
                try
                {
                    query.Value    = ReflectorHelper.ValueConvert(p, value);
                    query.ValueMin = ReflectorHelper.ValueConvert(p, item.Search.ValueMin);
                    query.ValueMax = ReflectorHelper.ValueConvert(p, item.Search.ValueMax);

                    //if (query.ValueMax != null && query.ValueMax is DateTime)
                    //{
                    //    query.ValueMax = ((DateTime)query.ValueMax).AddDays(1).AddMilliseconds(-1);
                    //}
                }
                catch (Exception e)
                {
                    continue;
                }

                query.Operator = item.Search.Opeartor;
                queryCollection.Add(query);
            }
            return(queryCollection.AsExpression <T>(Query.Condition.AndAlso));
        }
        public Expression <Func <T, bool> > AsExpression <T>(Query.Condition?condition = Query.Condition.OrElse) where T : class
        {
            Type       targetType = typeof(T);
            TypeInfo   typeInfo   = targetType.GetTypeInfo();
            var        parameter  = Expression.Parameter(targetType, ParameterSymbol);
            Expression expression = null;
            Func <Expression, Expression, Expression> Append = (exp1, exp2) =>
            {
                if (exp1 == null)
                {
                    return(exp2);
                }
                return((condition ?? Query.Condition.OrElse) == Query.Condition.OrElse ? Expression.OrElse(exp1, exp2) : Expression.AndAlso(exp1, exp2));
            };

            foreach (var item in this)
            {
                Expression property = GetPropertyExpression(parameter, item.Name);
                if (property == null ||
                    (item.Operator != Query.Operators.Range && item.Value == null) ||
                    (item.Operator == Query.Operators.Range && item.ValueMin == null && item.ValueMax == null))
                {
                    continue;
                }
                Type realType = Nullable.GetUnderlyingType(property.Type) ?? property.Type;
                if (item.Value != null)
                {
                    if (realType.GetTypeInfo().IsEnum)
                    {
                        Type underlyingType = Enum.GetUnderlyingType(realType);
                        item.Value = Convert.ChangeType(item.Value, underlyingType);
                        property   = Expression.Convert(property, underlyingType);
                    }
                    else if (item.Value.GetType().IsArray)
                    {
                        var objArray = item.Value as object[];

                        item.Value = ReflectorHelper.ValueConvert(realType, objArray);
                    }
                    else
                    {
                        item.Value = Convert.ChangeType(item.Value, realType);
                    }
                }
                Expression <Func <object> > valueLamba = () => item.Value;
                switch (item.Operator)
                {
                case Query.Operators.Equal:
                {
                    expression = Append(expression, Expression.Equal(property,
                                                                     Expression.Convert(valueLamba.Body, property.Type)));
                    break;
                }

                case Query.Operators.GreaterThan:
                {
                    expression = Append(expression, Expression.GreaterThan(property,
                                                                           Expression.Convert(valueLamba.Body, property.Type)));
                    break;
                }

                case Query.Operators.GreaterThanOrEqual:
                {
                    expression = Append(expression, Expression.GreaterThanOrEqual(property,
                                                                                  Expression.Convert(valueLamba.Body, property.Type)));
                    break;
                }

                case Query.Operators.LessThan:
                {
                    expression = Append(expression, Expression.LessThan(property,
                                                                        Expression.Convert(valueLamba.Body, property.Type)));
                    break;
                }

                case Query.Operators.LessThanOrEqual:
                {
                    expression = Append(expression, Expression.LessThanOrEqual(property,
                                                                               Expression.Convert(valueLamba.Body, property.Type)));
                    break;
                }

                case Query.Operators.Contains:
                {
                    var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property));
                    var contains  = Expression.Call(property, "Contains", null,
                                                    Expression.Convert(valueLamba.Body, property.Type));
                    expression = Append(expression, Expression.AndAlso(nullCheck, contains));
                    break;
                }

                case Query.Operators.In:    //value必须是数组类型
                {
                    var  constantExp    = Expression.Constant(item.Value, item.Value.GetType());
                    Type typeIfNullable = Nullable.GetUnderlyingType(property.Type);
                    if (typeIfNullable != null)
                    {
                        property = Expression.Call(property, "GetValueOrDefault", Type.EmptyTypes);
                    }
                    var contains = Expression.Call(typeof(Enumerable), "Contains", new Type[] { realType }, constantExp, property);
                    //var contains = Expression.Call(constantExp, "Contains", null, property);
                    expression = Append(expression, contains);
                    break;
                }

                case Query.Operators.StartWith:
                {
                    var nullCheck  = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property));
                    var startsWith = Expression.Call(property, "StartsWith", null,
                                                     Expression.Convert(valueLamba.Body, property.Type));
                    expression = Append(expression, Expression.AndAlso(nullCheck, startsWith));
                    break;
                }

                case Query.Operators.EndWidth:
                {
                    var nullCheck = Expression.Not(Expression.Call(typeof(string), "IsNullOrEmpty", null, property));
                    var endsWith  = Expression.Call(property, "EndsWith", null,
                                                    Expression.Convert(valueLamba.Body, property.Type));
                    expression = Append(expression, Expression.AndAlso(nullCheck, endsWith));
                    break;
                }

                case Query.Operators.Range:
                {
                    Expression minExp = null, maxExp = null;
                    if (item.ValueMin != null)
                    {
                        var minValue = Convert.ChangeType(item.ValueMin, realType);
                        Expression <Func <object> > minValueLamda = () => minValue;
                        minExp = Expression.GreaterThanOrEqual(property, Expression.Convert(minValueLamda.Body, property.Type));
                    }
                    if (item.ValueMax != null)
                    {
                        var maxValue = Convert.ChangeType(item.ValueMax, realType);
                        Expression <Func <object> > maxValueLamda = () => maxValue;
                        maxExp = Expression.LessThanOrEqual(property, Expression.Convert(maxValueLamda.Body, property.Type));
                    }

                    if (minExp != null && maxExp != null)
                    {
                        expression = Append(expression, Expression.AndAlso(minExp, maxExp));
                    }
                    else if (minExp != null)
                    {
                        expression = Append(expression, minExp);
                    }
                    else if (maxExp != null)
                    {
                        expression = Append(expression, maxExp);
                    }

                    break;
                }
                }
            }
            if (expression == null)
            {
                return(null);
            }
            return((Expression <Func <T, bool> >)Expression.Lambda(expression, parameter));
        }
        public LambdaExpression GetExpression(Dictionary <string, object> enviromens = null)
        {
            FilterValues = FilterValue?.Split(',');
            if (enviromens != null && enviromens.ContainsKey(FilterValue))
            {
                var realValue     = enviromens[FilterValue];
                var realValueType = realValue.GetType();
                if (realValueType.GetInterface(nameof(IEnumerable)) != null && typeof(string) != realValueType)
                {
                    realValueType = realValueType.GetGenericArguments()[0];
                    MethodInfo toArrayMethod = typeof(Enumerable).GetMethod("ToArray")
                                               .MakeGenericMethod(new System.Type[] { realValueType });
                    FilterValues = toArrayMethod.Invoke(null, new object[] { realValue }) as object[];
                }

                else
                {
                    FilterValues = new object[] { realValue }
                };

                if (Type.GetType(this.PropertyType) != realValueType)
                {
                    throw new NotSupportedException("the propertyType can not compare to the value type ");
                }
            }

            PropertyPath = string.Join(".", PropertyNames);
            var enityType = Type.GetType(EntityType);
            LambdaExpression lambdaExpression = null;
            var parameter = Expression.Parameter(enityType, QueryCollection.ParameterSymbol);

            switch (FieldKind)
            {
            case FieldKind.ValueType:     //如:m.Id==2 或者m.Name.Contains("a") 或者m.Group.Name="a"
            case FieldKind.Reference:     //reference下的属性处理与ValueType是一致的,其实可以忽略掉
            {
                var queryCollection = new QueryCollection();
                var query           = new Query {
                    Name = this.PropertyPath, Operator = this.Operator
                };
                switch (query.Operator)
                {
                case Operators.Range:
                {
                    query.ValueMin = this.FilterValues[0];
                    query.ValueMax = this.FilterValues[1];
                    break;
                }

                case Operators.In:
                {
                    query.Value = this.FilterValues;
                    break;
                }

                default:
                    query.Value = this.FilterValues[0];
                    break;
                }
                queryCollection.Add(query);
                var method = typeof(QueryCollection).GetMethod("AsExpression");
                method = method.MakeGenericMethod(enityType);

                lambdaExpression = (LambdaExpression)method.GetReflector().Invoke(queryCollection, Query.Condition.AndAlso);
                break;
            }

            case FieldKind.ICollection:
            {
                if (this.RuleGroup == null)
                {
                    break;
                }
                var childLambda = this.RuleGroup.GetExpression();

                var member = QueryCollection.GetPropertyExpression(parameter, PropertyPath);
                if (member.Type.GetInterface(nameof(IEnumerable)) != null)
                {
                    lambdaExpression = Expression.Lambda(
                        Expression.Call(typeof(Enumerable), "Any", new Type[] { Type.GetType(this.RuleGroup.EntityType) }, member, childLambda),
                        parameter);
                }
                break;
            }

            case FieldKind.EnvType:    //用户的上下文环境变量,在json字符串阶段需提前用变量值替换掉,替换后,propertyPath其实就是一个值
            {
                var propertyType = Type.GetType(this.PropertyType);
                if (enviromens == null)
                {
                    throw new ArgumentNullException("enviroment values is null");
                }
                if (!enviromens.ContainsKey(this.PropertyPath))
                {
                    throw new ArgumentNullException("not such enviroment key and value");
                }
                var environmentValue = enviromens[this.PropertyPath];
                var left             = Expression.Constant(environmentValue);

                Expression expression = null;
                switch (Operator)
                {
                case Query.Operators.Equal:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                    expression = Expression.Equal(left, right);
                    break;
                }

                case Query.Operators.GreaterThan:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                    expression = Expression.GreaterThan(left, right);

                    break;
                }

                case Query.Operators.GreaterThanOrEqual:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                    expression = Expression.GreaterThanOrEqual(left, right);

                    break;
                }

                case Query.Operators.LessThan:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                    expression = Expression.LessThan(left, right);

                    break;
                }

                case Query.Operators.LessThanOrEqual:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                    expression = Expression.LessThanOrEqual(left, right);

                    break;
                }

                case Query.Operators.Contains:
                {
                    var itemType = propertyType != typeof(string) && propertyType.GetInterface(nameof(IEnumerable)) != null ? propertyType.GenericTypeArguments[0] : propertyType;
                    var right    = Expression.Constant(ReflectorHelper.ValueConvert(itemType, FilterValues[0]));
                    expression = Expression.Call(left, "Contains", null, right);
                    break;
                }

                case Query.Operators.In:            //value必须是集合类型
                {
                    var constantVaule = ReflectorHelper.ValueConvert(propertyType, FilterValues);
                    var right         = Expression.Constant(constantVaule);

                    expression = Expression.Call(typeof(Enumerable), "Contains", new Type[] { propertyType }, right, left);

                    break;
                }

                case Query.Operators.StartWith:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));

                    expression = Expression.Call(left, "StartsWith", null, right);

                    break;
                }

                case Query.Operators.EndWidth:
                {
                    var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));

                    expression = Expression.Call(left, "EndsWith", null, right);
                    break;
                }

                case Query.Operators.Range:
                {
                    Expression minExp = null, maxExp = null;
                    if (FilterValues.Length > 0 && FilterValues[0] != null)
                    {
                        var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[0]));
                        minExp = Expression.GreaterThanOrEqual(left, right);
                    }
                    if (FilterValues.Length > 1 && FilterValues[1] != null)
                    {
                        var right = Expression.Constant(ReflectorHelper.ValueConvert(propertyType, FilterValues[1]));
                        maxExp = Expression.LessThanOrEqual(left, right);
                    }

                    if (minExp != null && maxExp != null)
                    {
                        expression = Expression.AndAlso(minExp, maxExp);
                    }
                    else if (minExp != null)
                    {
                        expression = minExp;
                    }
                    else if (maxExp != null)
                    {
                        expression = maxExp;
                    }

                    break;
                }
                }
                lambdaExpression = Expression.Lambda(expression, parameter);
                break;
            }

            default:
                break;
            }


            return(lambdaExpression);
        }
    }