Exemplo n.º 1
0
        public static IQueryable <T> OrderBy <T>(this IQueryable <T> query, string orderBySpec, IDictionary <string, string> nameMapping = null)
        {
            if (string.IsNullOrWhiteSpace(orderBySpec))
            {
                return(query);
            }
            var    memberInfos = typeof(T).GetAllProperties();
            string propRef;
            bool   isDesc;
            var    segments = orderBySpec.SplitNames();

            foreach (var segm in segments)
            {
                if (string.IsNullOrWhiteSpace(segm))
                {
                    continue;
                }
                var arr = segm.SplitNames(':', '-'); // '-' is better for URLs, ':' is a special symbol, must be escaped
                if (arr.Length < 2)
                {
                    propRef = segm;
                    isDesc  = false;
                }
                else
                {
                    propRef = arr[0];
                    var ascDesc = arr[1].Trim().ToUpper();
                    if (!string.IsNullOrEmpty(ascDesc))
                    {
                        Util.Check(ascDesc == "ASC" || ascDesc == "DESC", "Invalid OrderBy spec, ASC/DESC flag: '{0}'", ascDesc);
                    }
                    isDesc = ascDesc == "DESC";
                }
                Util.Check(!string.IsNullOrWhiteSpace(propRef), "Invalid OrderBy spec, empty property ref: '{0}'", orderBySpec);
                //Build expression ent => ent.Prop
                string mappedName;
                if (nameMapping != null && nameMapping.TryGetValue(propRef, out mappedName))
                {
                    propRef = mappedName;
                }
                //propRef might be a chain of reads: User.Person.FirstName; let's unpack it and build expression
                var prm       = Expression.Parameter(typeof(T), "@ent");
                var memberGet = ExpressionHelper.BuildChainedPropReader(prm, propRef);
                var lambda    = Expression.Lambda <Func <T, object> >(memberGet, prm);
                // Note: we might need to use ThenBy and ThenByDescending here for all clauses after first.
                // But it looks like it works OK, at least in SQL, the ORDER BY clause is correct
                query = isDesc ? query.OrderByDescending(lambda) : query.OrderBy(lambda);
            }
            return(query);
        }//method