/// <summary>
        /// Order an <see cref="IQueryable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitems"><see cref="IEnumerable{IOrderItem}"/></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> OrderBy <TSource>(this IQueryable <TSource> source, IEnumerable <IOrderItem> orderitems)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!orderitems.Any())
            {
                return((IOrderedQueryable <TSource>)source);
            }

            var isOrderby = true;
            var processed = false;
            //Can not convert source to IOrderedQueryable
            //  => gives error
            IOrderedQueryable <TSource> returnOrder = null;

            foreach (var orderitem in orderitems)
            {
                returnOrder = isOrderby
                    ? OrderByInternal.QueryableOrder(source, orderitem, out processed)
                    : OrderByInternal.QueryableOrderThenBy(returnOrder, orderitem);

                if (isOrderby && processed)
                {
                    isOrderby = false;
                }
            }

            return(returnOrder);
        }
        /// <summary>
        /// Order <see cref="IOrderedQueryable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitem"><see cref="IOrderItem"/></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> ThenBy <TSource>(this IOrderedQueryable <TSource> source, IOrderItem orderitem)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            return(OrderByInternal.QueryableOrderThenBy(source, orderitem));
        }
        /// <summary>
        /// Order <see cref="IOrderedQueryable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum">name of the column to sort on</param>
        /// <param name="orderDirection"><see cref="OrderDirectionEnum"/></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> ThenBy <TSource>(this IOrderedQueryable <TSource> source, string sortColum, OrderDirectionEnum orderDirection)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            return(OrderByInternal.QueryableOrderThenBy(source, new OrderItem {
                SortColum = sortColum, OrderDirection = orderDirection
            }));
        }
        /// <summary>
        /// Order <see cref="IOrderedQueryable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum">name of the column to sort on</param>
        /// <param name="isDescending">Is the order direction descending</param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> ThenBy <TSource>(this IOrderedQueryable <TSource> source, string sortColum, bool isDescending)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            return(OrderByInternal.QueryableOrderThenBy(source, new OrderItem {
                SortColum = sortColum, OrderDirection = Orderby.GetOrderDirection(isDescending)
            }));
        }
        /// <summary>
        /// Order an <see cref="IQueryable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum">name of the column to sort on</param>
        /// <param name="sortDirection">the order by which to sort</param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> OrderBy <TSource>(this IQueryable <TSource> source, string sortColum, string sortDirection)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            return(OrderByInternal.QueryableOrder(source, new OrderItem {
                SortColum = sortColum, OrderDirection = Orderby.GetOrderDirection(sortDirection)
            }, out _));
        }
        /// <summary>
        /// Order <see cref="IOrderedQueryable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitem"><see cref="IOrderItem"/></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> ThenBy <TSource, TKey>(this IOrderedQueryable <TSource> source, OrderItem <TKey> orderitem)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrWhiteSpace(orderitem.SortColum))
            {
                throw new ArgumentException("Input cannot be null or empty", "orderitem.SortColum");
            }

            return(OrderByInternal.QueryableOrderThenBy(source, orderitem));
        }
        /// <summary>
        /// Order an <see cref="IEnumerable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitem"><see cref="IOrderItem"/></param>
        /// <returns></returns>
        public static IOrderedEnumerable <TSource> OrderBy <TSource>(this IEnumerable <TSource> source, IOrderItem orderitem)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrWhiteSpace(orderitem.SortColum))
            {
                throw new ArgumentException("Input cannot be null or empty", "orderitem.SortColum");
            }

            return(OrderByInternal.EnumerableOrder(source, orderitem, out _));
        }
        /// <summary>
        /// Order <see cref="IOrderedQueryable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum"></param>
        /// <param name="orderDirection"><see cref="OrderDirectionEnum"/></param>
        /// <param name="comparer"><see cref="IComparer{TKey}" /></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> ThenBy <TSource, TKey>(this IOrderedQueryable <TSource> source, string sortColum, OrderDirectionEnum orderDirection, IComparer <TKey> comparer)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrWhiteSpace(sortColum))
            {
                throw new ArgumentException("Input cannot be null or empty", "sortColum");
            }

            return(OrderByInternal.QueryableOrderThenBy(source, new OrderItem <TKey> {
                SortColum = sortColum, OrderDirection = orderDirection, Comparer = comparer
            }));
        }
        /// <summary>
        /// Order an <see cref="IEnumerable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum">name of the column to sort on</param>
        /// <param name="isDescending">Is the order direction descending</param>
        /// <returns></returns>
        public static IOrderedEnumerable <TSource> OrderBy <TSource>(this IEnumerable <TSource> source, string sortColum, bool isDescending)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrWhiteSpace(sortColum))
            {
                throw new ArgumentException("Input cannot be null or empty", "sortColum");
            }

            return(OrderByInternal.EnumerableOrder(source, new OrderItem {
                SortColum = sortColum, OrderDirection = Orderby.GetOrderDirection(isDescending)
            }, out _));
        }
        /// <summary>
        /// Order <see cref="IOrderedEnumerable{TSource}"/> then by
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitems"><see cref="IEnumerable{IOrderItem}"/></param>
        /// <returns></returns>
        public static IOrderedEnumerable <TSource> ThenBy <TSource>(this IOrderedEnumerable <TSource> source, IEnumerable <IOrderItem> orderitems)
        {
            if (orderitems == null)
            {
                throw new ArgumentNullException("orderitems");
            }

            var returnOrder = source;

            foreach (var orderitem in orderitems)
            {
                returnOrder = OrderByInternal.EnumerableOrderThenBy(returnOrder, orderitem);
            }

            return(returnOrder);
        }
        /// <summary>
        /// Order an <see cref="IQueryable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TKey"></typeparam>
        /// <param name="source"></param>
        /// <param name="sortColum">Comma or semicolumn seperated string expression of the colume and direction. Directon is not mandatory, if not pressend then it will be ascending</param>
        /// <param name="isDescending">Is the order direction descending</param>
        /// <param name="comparer"><see cref="IComparer{TKey}" /></param>
        /// <returns></returns>
        public static IOrderedQueryable <TSource> OrderBy <TSource, TKey>(this IQueryable <TSource> source, string sortColum, bool isDescending, IComparer <TKey> comparer)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrWhiteSpace(sortColum))
            {
                throw new ArgumentException("Input cannot be null or empty", "sortColum");
            }

            return(OrderByInternal.QueryableOrder(source, new OrderItem <TKey> {
                SortColum = sortColum, OrderDirection = Orderby.GetOrderDirection(isDescending), Comparer = comparer
            }, out _));
        }
        /// <summary>
        /// Order an <see cref="IEnumerable{TSource}"/>
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <param name="source"></param>
        /// <param name="orderitems"><see cref="IEnumerable{IOrderItem}"/></param>
        /// <returns></returns>
        public static IOrderedEnumerable <TSource> OrderBy <TSource>(this IEnumerable <TSource> source, IEnumerable <IOrderItem> orderitems)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (!orderitems.Any())
            {
                throw new ArgumentNullException("orderitems");
            }

            if (orderitems.Any(c => string.IsNullOrWhiteSpace(c.SortColum)))
            {
                throw new ArgumentException("Input cannot be null or empty", "orderitems.SortColum");
            }

            var isOrderby = true;
            var processed = false;
            //Can not convert source to IOrderedQueryable
            //  => gives error
            IOrderedEnumerable <TSource> returnOrder = null;

            foreach (var orderitem in orderitems)
            {
                returnOrder = isOrderby
                    ? OrderByInternal.EnumerableOrder(source, orderitem, out processed)
                    : OrderByInternal.EnumerableOrderThenBy(returnOrder, orderitem);

                if (isOrderby && processed)
                {
                    isOrderby = false;
                }
            }

            return(returnOrder);
        }