Dynamic Paging and Sorting

Posted by Ricardo Peres on ASP.net Weblogs See other posts from ASP.net Weblogs or by Ricardo Peres
Published on Fri, 09 Apr 2010 13:27:00 GMT Indexed on 2010/04/09 13:33 UTC
Read the original article Hit count: 784

Filed under:
|
|

Since .NET 3.5 brought us LINQ and expressions, I became a great fan of these technologies. There are times, however, when strong typing cannot be used - for example, when you are developing an ObjectDataSource and you need to do paging having just a column name, a page index and a page size, so I set out to fix this. Yes, I know about Dynamic LINQ, and even talked on it previously, but there's no need to add this extra assembly.

So, without further delay, here's the code, in both generic and non-generic versions:


public static IList ApplyPagingAndSorting(IEnumerable enumerable, Type elementType, Int32 pageSize, Int32 pageIndex, params String [] orderByColumns)
{
	MethodInfo asQueryableMethod = typeof(Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public).Where(m => (m.Name == "AsQueryable") && (m.ContainsGenericParameters == false)).Single();
	IQueryable query = (enumerable is IQueryable) ? (enumerable as IQueryable) : asQueryableMethod.Invoke(null, new Object [] { enumerable }) as IQueryable;

	if ((orderByColumns != null) && (orderByColumns.Length > 0))
	{
		PropertyInfo orderByProperty = elementType.GetProperty(orderByColumns [ 0 ]);
		MemberExpression member = Expression.MakeMemberAccess(Expression.Parameter(elementType, "n"), orderByProperty);
		LambdaExpression orderBy = Expression.Lambda(member, member.Expression as ParameterExpression);
		MethodInfo orderByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "OrderBy").ToArray() [ 0 ].MakeGenericMethod(elementType, orderByProperty.PropertyType);

		query = orderByMethod.Invoke(null, new Object [] { query, orderBy }) as IQueryable;

		if (orderByColumns.Length > 1)
		{
			MethodInfo thenByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "ThenBy").ToArray() [ 0 ].MakeGenericMethod(elementType, orderByProperty.PropertyType);
			PropertyInfo thenByProperty = null;
			MemberExpression thenByMember = null;
			LambdaExpression thenBy = null;

			for (Int32 i = 1; i < orderByColumns.Length; ++i)
			{
				thenByProperty = elementType.GetProperty(orderByColumns [ i ]);
				thenByMember = Expression.MakeMemberAccess(Expression.Parameter(elementType, "n"), thenByProperty);
				thenBy = Expression.Lambda(member, member.Expression as ParameterExpression);
				query = thenByMethod.Invoke(null, new Object [] { query, thenBy }) as IQueryable;
			}
		}
	}

	if (pageSize > 0)
	{
		MethodInfo takeMethod = typeof(Queryable).GetMethod("Take", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType);
		MethodInfo skipMethod = typeof(Queryable).GetMethod("Skip", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(elementType);

		query = skipMethod.Invoke(null, new Object [] { query, pageSize * pageIndex }) as IQueryable;
		query = takeMethod.Invoke(null, new Object [] { query, pageSize }) as IQueryable;
	}

	MethodInfo toListMethod = typeof(Enumerable).GetMethod("ToList", BindingFlags.Static | BindingFlags.Public).MakeGenericMethod(elementType);
	IList list = toListMethod.Invoke(null, new Object [] { query }) as IList;

	return (list);
}

public static List ApplyPagingAndSorting(IEnumerable enumerable, Int32 pageSize, Int32 pageIndex, params String [] orderByColumns)
{
	return (ApplyPagingAndSorting(enumerable, typeof(T), pageSize, pageIndex, orderByColumns) as List);
}

List list = new List { new DateTime(2010, 1, 1), new DateTime(1999, 1, 12), new DateTime(1900, 10, 10), new DateTime(1900, 2, 20), new DateTime(2012, 5, 5), new DateTime(2012, 1, 20) };
List sortedList = ApplyPagingAndSorting(list, 3, 0, "Year", "Month", "Day");

Bookmark and Share

© ASP.net Weblogs or respective owner

Related posts about .NET

Related posts about LINQ