Is it possible to create a reusable LINQ
query expression with calls to OrderBy
and Where
, without applying it to a specific IQueryable
?
I would like to be able to do something like this:
var data = new List<PlayerDTO>();
var builder = new Builder<PlayerDTO>();
var query = builder.GetQuery();
var results = data.AsQueryable().Provider.CreateQuery(query);
I have trouble getting this to work without providing the IQueryable
object to the GetQuery
method.
This is the code I have so far:
public Expression GetQuery()
{
var type = typeof(T); // T is PlayerDTO
var col = type.GetProperty(OrderBy.Column);
var orderByMethod = typeof(Queryable).GetMethods().Single(
method => method.Name == "OrderBy"
&& method.IsGenericMethodDefinition
&& method.GetGenericArguments().Length == 2
&& method.GetParameters().Length == 2);
var genericOrdebyMethod = orderByMethod.MakeGenericMethod(typeof(T), col.PropertyType);
var parameter = Expression.Parameter(typeof(T), "p"); // {p}
var property = Expression.Property(parameter, col); // {p.ID}
var lambda = Expression.Lambda<Func<T, int>>(property, parameter); // {p => p.ID}
//This list should not exist here
var tempList = new List<PlayerDTO>() { new PlayerDTO(1, "First"), new PlayerDTO(2, "Second") };
var orderByMethodExpression = Expression.Call(genericOrdebyMethod, tempList.AsQueryable().Expression, lambda); // {tempList.OrderBy(p => p.ID)}
var results = tempList.AsQueryable().Provider.CreateQuery(orderByMethodExpression);
return orderByMethodExpression;
}
The relevant part is the call to Expression.Call
, where I had to provide an IQueryable
so it would work, but I would like to be able to build the expression without specifying an existing IQueryable
.
Is this even possible?
Edit:
Now that I think about this, I actually don't need to do this at all... It makes perfect sense to just send the IQueryable as a parameter to the GetQuery method. I will keep this question up though.
You could create it as another expression from IQueryable to IOrderedQueryable, something like:
I use it this way, and my list get ordered: