Dynamic LINQ Methods

Continuing the Dynamic LINQ series, here are some hopefuly useful methods for performing LINQ queries in IQueryable or IQueryable<T> object, with String parameters. The available methods, so far, are:

  • GroupBy
  • OrderBy
  • Skip
  • Take
  • WhereEquals
  • WhereNotEquals

	public static class QueryableExtensions
	{
		public static IQueryable<T&> WhereNotEquals<T&>(this IQueryable<T&> query, String propertyName, Object value)
		{
			return (WhereNotEquals(query as IQueryable, propertyName, value) as IQueryable<T&>);
		}

		public static IQueryable WhereNotEquals(this IQueryable query, String propertyName, Object value)
		{
			Type propertyType = query.GetType().GetGenericArguments() [ 0 ];
			MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "Where").ToArray() [ 0 ].MakeGenericMethod(propertyType);

			ParameterExpression parameter = Expression.Parameter
			(
				propertyType,
				"m"
			);

			MemberExpression member = Expression.MakeMemberAccess
			(
				parameter,
				propertyType.GetProperty(propertyName)
			);

			BinaryExpression equal = ParameterExpression.NotEqual
			(
				member,
				(value != null) ? Expression.Constant(value, value.GetType()) : null
			);

			LambdaExpression lambda = Expression.Lambda
			(
				typeof(Func<,>).MakeGenericType(propertyType, typeof(Boolean)),
				equal,
				member.Expression as ParameterExpression
			);

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

			return (query);
		}

		public static IQueryable<T&> WhereEquals<T&>(this IQueryable<T&> query, String propertyName, Object value)
		{
			return (WhereEquals(query as IQueryable, propertyName, value) as IQueryable<T&>);
		}

		public static IQueryable WhereEquals(this IQueryable query, String propertyName, Object value)
		{
			Type propertyType = query.GetType().GetGenericArguments() [ 0 ];
			MethodInfo whereMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "Where").ToArray() [ 0 ].MakeGenericMethod(propertyType);

			ParameterExpression parameter = Expression.Parameter
			(
				propertyType,
				"m"
			);

			MemberExpression member = Expression.MakeMemberAccess
			(
				parameter,
				propertyType.GetProperty(propertyName)
			);

			BinaryExpression equal = ParameterExpression.Equal
			(
				member,
				(value != null) ? Expression.Constant(value, value.GetType()) : null
			);

			LambdaExpression lambda = Expression.Lambda(typeof(Func<,>).MakeGenericType(propertyType, typeof(Boolean)), equal, member.Expression as ParameterExpression);

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

			return(query);
		}

		public static IQueryable<T&> GroupBy<T&>(this IQueryable<T&> query, String propertyName)
		{
			return (GroupBy(query as IQueryable, propertyName) as IQueryable<T&>);
		}

		public static IQueryable GroupBy(this IQueryable query, String propertyName)
		{
			Type propertyType = query.GetType().GetGenericArguments() [ 0 ];
			PropertyInfo property = propertyType.GetProperty(propertyName, BindingFlags.Instance | BindingFlags.Public);
			MethodInfo groupByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "GroupBy" && m.GetParameters().Length == 2).ToArray() [ 0 ].MakeGenericMethod(propertyType, property.PropertyType);

			ParameterExpression parameter = Expression.Parameter
			(
				propertyType,
				"m"
			);

			MemberExpression member = Expression.MakeMemberAccess
			(
				parameter,
				propertyType.GetProperty(propertyName)
			);
	
			LambdaExpression lambda = Expression.Lambda
			(
				typeof(Func<,>).MakeGenericType(propertyType, property.PropertyType),
				member,
				member.Expression as ParameterExpression
			);

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

			return (query);
		}

		public static IQueryable<T&> OrderBy<T&>(this IQueryable<T&> query, params String [] properties)
		{
			return (OrderBy(query as IQueryable, properties) as IQueryable<T&>);
		}

		public static IQueryable OrderBy(this IQueryable query, params String [] properties)
		{
			properties = (properties == null) ? new String [ 0 ] : properties.Distinct().ToArray();

			Type propertyType = query.GetType().GetGenericArguments()[ 0 ];
			MethodInfo orderByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "OrderBy").ToArray() [ 0 ];
			MethodInfo orderByDescMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "OrderByDescending").ToArray() [ 0 ];
			MethodInfo orderThenByMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "ThenBy").ToArray() [ 0 ];
			MethodInfo orderThenByDescMethod = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => m.Name == "ThenByDescending").ToArray() [ 0 ];
			String [] parts = null;
			MethodInfo method = null;
			PropertyInfo property = null;
			MemberExpression member = null;
			LambdaExpression orderBy = null;

			for (Int32 i = 0; i < properties.Length; ++i)
			{
				parts = properties[ i ].Split(' ');

				property = propertyType.GetProperty(parts[ 0 ], BindingFlags.Instance | BindingFlags.Public);

				if ((parts.Length == 1) || (parts [ 1 ].Equals("asc", StringComparison.OrdinalIgnoreCase) == true))
				{
					if (i == 0)
					{
						method = orderByMethod.MakeGenericMethod(propertyType, property.PropertyType);
					}
					else
					{
						method = orderThenByMethod.MakeGenericMethod(propertyType, property.PropertyType);
					}
				}
				else if (parts[ 1 ].Equals("desc", StringComparison.OrdinalIgnoreCase) == true)
				{
					if (i == 0)
					{
						method = orderByDescMethod.MakeGenericMethod(propertyType, property.PropertyType);
					}
					else
					{
						method = orderThenByDescMethod.MakeGenericMethod(propertyType, property.PropertyType);
					}
				}

				member = Expression.MakeMemberAccess
				(
					Expression.Parameter(propertyType, "n"),
					property
				);

				orderBy = Expression.Lambda
				(
					member,
					member.Expression as ParameterExpression
				);

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

			return (query);
		}

		public static IQueryable Take(this IQueryable query, Int32 pageSize)
		{
			Type propertyType = query.GetType().GetGenericArguments() [ 0 ];
			MethodInfo takeMethod = typeof(Queryable).GetMethod("Take", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(propertyType);

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

			return (query);
		}

		public static IQueryable Skip(this IQueryable query, Int32 pageIndex)
		{
			Type propertyType = query.GetType().GetGenericArguments() [ 0 ];
			MethodInfo skipMethod = typeof(Queryable).GetMethod("Skip", BindingFlags.Public | BindingFlags.Static).MakeGenericMethod(propertyType);

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

			return (query);
		}
	}

Here are some examples:


IQueryable q = ...;

q = q.OrderBy("NAME asc", "BIRTHDAY desc");

q = q.WhereEquals("NAME", "bla");

q = q.GroupBy("PROFILE");

q = q.Take(10);

Bookmark and Share

                             

2 Comments

Comments have been disabled for this content.