public override KeyValuePair <string, Expression>?GetExpression <TSource>(Type sourceType, ParameterExpression rootParameter, IEnumerable <TSource> source)
        {
            // 1. Parse the instruction.
            var fieldNames   = Parameter.Split(',');
            var instructions = fieldNames.Select(s =>
            {
                return(InstructionHelper.ExtractInstruction(s));
            }).Where(s => s.HasValue);

            if (instructions.Count() == 0)
            {
                throw new ArgumentException("the parameter cannot be empty");
            }

            if (instructions.Any(i => !_orderByInstructions.Contains(i.Value.Key)))
            {
                throw new ArgumentException("At least one instruction is not supported");
            }

            var onInstruction    = instructions.FirstOrDefault(i => i.Value.Key == _onInstruction);
            var orderInstruction = instructions.FirstOrDefault(i => i.Value.Key == _orderInstruction);

            if (onInstruction == null)
            {
                throw new ArgumentException("The 'on' instruction must be specified");
            }

            var fnName = "OrderBy";

            if (orderInstruction != null && orderInstruction.Value.Value == "desc")
            {
                fnName = "OrderByDescending";
            }

            // 2. Construct the selector.
            ParameterExpression arg      = Expression.Parameter(sourceType, "x");
            MemberExpression    property = Expression.Property(arg, onInstruction.Value.Value);
            var selector = Expression.Lambda(property, new ParameterExpression[] { arg });

            // 3. Call the order function and return the result.
            var enumarableType = typeof(Queryable);
            var method         = enumarableType.GetMethods()
                                 .Where(m => m.Name == fnName && m.IsGenericMethodDefinition)
                                 .Where(m =>
            {
                var parameters = m.GetParameters().ToList();
                return(parameters.Count == 2);
            }).Single().MakeGenericMethod(sourceType, property.Type);

            if (SubInstruction != null)
            {
                var subExpr = SubInstruction.GetExpression(sourceType, rootParameter, source);
                var call    = Expression.Call(method, subExpr.Value.Value, selector);
                return(new KeyValuePair <string, Expression>(Name, call));
            }

            return(new KeyValuePair <string, Expression>(Name, Expression.Call(method, rootParameter, selector)));
        }
        public override KeyValuePair <string, Expression>?GetExpression <TSource>(Type sourceType, ParameterExpression rootParameter, IEnumerable <TSource> source)
        {
            const string condExpression = "(\\w|-|_|@)* (eq|neq|co|sw|ew|lt|le|gt|ge) ('|\")((\\w|-|_|@)| |\\d|:|\\/)*('|\")";
            const string expression     = "((\\w|-|_|@)* (eq|neq|co|sw|ew|lt|le|gt|ge) (('|\")((\\w|-|_|@)| |\\d|:|\\/)*('|\")( and | or ){0,1}))+";
            var          match          = Regex.Match(Parameter, expression);

            if (string.IsNullOrWhiteSpace(match.Value) || match.Value != Parameter)
            {
                throw new InvalidOperationException($"the parameter {Parameter} is not correct");
            }

            Type       sourceQueryableType = null;
            Expression subExpression       = null;

            if (SubInstruction != null)
            {
                var subExpr = SubInstruction.GetExpression(sourceType, rootParameter, source);
                subExpression = subExpr.Value.Value;
                sourceType    = subExpression.Type.GetGenericArguments().First();
            }

            var conds      = Regex.Matches(Parameter, condExpression);
            var ops        = Regex.Split(Regex.Replace(Parameter, condExpression, ""), " *(and|or) *").Where(s => !string.IsNullOrWhiteSpace(s));
            var conditions = new List <string>();
            int ind        = 0;

            foreach (Match cond in conds)
            {
                conditions.Add(cond.Value);
                if (ops.Count() - 1 < ind)
                {
                    continue;
                }

                conditions.Add(ops.ElementAt(ind));
                ind++;
            }

            var        arg        = Expression.Parameter(sourceType, "x");
            Expression binaryExpr = null;

            if (conditions.Count() != 1)
            {
                Expression     rightOperand = null;
                ExpressionType type         = ExpressionType.AndAlso;
                for (var i = conditions.Count() - 1; i >= 0; i--)
                {
                    var str = conditions.ElementAt(i);
                    if ((i + 1) % 2 == 0)
                    {
                        if (str == "or")
                        {
                            type = ExpressionType.Or;
                        }
                        else
                        {
                            type = ExpressionType.AndAlso;
                        }
                    }
                    else
                    {
                        var expr = BuildCondition(str, arg);
                        if (rightOperand == null)
                        {
                            rightOperand = expr;
                        }
                        else
                        {
                            rightOperand = Expression.MakeBinary(type, expr, rightOperand);
                        }
                    }
                }

                binaryExpr = rightOperand;
            }
            else
            {
                binaryExpr = BuildCondition(conditions.First(), arg);
            }

            sourceQueryableType = typeof(IQueryable <>).MakeGenericType(sourceType);
            var selector       = Expression.Lambda(binaryExpr, new ParameterExpression[] { arg });
            var enumarableType = typeof(Queryable);
            var genericMethod  = enumarableType.GetMethods()
                                 .Where(m => m.Name == "Where" && m.IsGenericMethodDefinition)
                                 .Where(m => m.GetParameters().Count() == 2).First().MakeGenericMethod(sourceType);

            if (subExpression != null)
            {
                var call = Expression.Call(genericMethod, subExpression, selector);
                return(new KeyValuePair <string, Expression>(Name, call));
            }

            return(new KeyValuePair <string, Expression>(Name, Expression.Call(genericMethod, rootParameter, selector)));
        }
        public override KeyValuePair <string, Expression>?GetExpression <TSource>(Type sourceType, ParameterExpression rootParameter, IEnumerable <TSource> source)
        {
            IEnumerable <string> fieldNames = null;

            if (!string.IsNullOrWhiteSpace(Parameter) && Parameter != _starSelector)
            {
                fieldNames = Parameter.GetParameters();
            }
            else
            {
                fieldNames = sourceType.GetProperties().Select(m => m.Name).ToArray();
            }

            // 1. Get sub expression.
            Expression subExpr    = null;
            Type       targetType = sourceType;

            if (SubInstruction != null)
            {
                var kvp = SubInstruction.GetExpression(sourceType, rootParameter, source).Value;
                subExpr    = kvp.Value;
                targetType = subExpr.Type.GetGenericArguments().First();
                if (string.IsNullOrWhiteSpace(Parameter))
                {
                    return(kvp);
                }
            }

            // x
            var arg = Expression.Parameter(targetType, "x");
            // f
            var finalSelectArg        = Expression.Parameter(typeof(IQueryable <>).MakeGenericType(targetType), "f");
            LambdaExpression selector = null;
            Type             type     = null;

            if (fieldNames.Count() == 1)
            {
                var field = fieldNames.First();
                MemberExpression property = Expression.Property(arg, field);
                selector = Expression.Lambda(property, new ParameterExpression[] { arg });
                type     = property.Type;
            }
            else
            {
                var sourceProperties = fieldNames.ToDictionary(name => name, name => sourceType.GetProperty(name));
                var anonType         = ReflectionHelper.CreateNewAnonymousType(sourceType, fieldNames);
                var exprNew          = ExpressionBuilder.BuildNew(fieldNames, sourceType, anonType, arg);
                selector = Expression.Lambda(exprNew, new ParameterExpression[] { arg });
                type     = anonType.AsType();
            }

            var enumarableType = typeof(Queryable);
            var selectMethod   = enumarableType.GetMethods()
                                 .Where(m => m.Name == "Select" && m.IsGenericMethodDefinition)
                                 .Where(m =>
            {
                var parameters = m.GetParameters().ToList();
                return(parameters.Count == 2);
            }).First().MakeGenericMethod(targetType, type);

            if (SubInstruction != null)
            {
                return(new KeyValuePair <string, Expression>(Name, Expression.Call(typeof(Queryable), "Select", new Type[] { targetType, type }, subExpr, selector)));
            }

            return(new KeyValuePair <string, Expression>(Name, Expression.Call(typeof(Queryable), "Select", new Type[] { targetType, type }, Expression.Constant(source), selector)));
        }