Reusable LINQ method query

c# dynamic-linq expression-trees linq

Question

Can a reusable system be developed?LINQ expression of query containing calls toOrderBy and Where without relating it to a particularIQueryable ?

I'd want to be able to do the following:

var data = new List<PlayerDTO>();
var builder = new Builder<PlayerDTO>();
var query = builder.GetQuery();
var results = data.AsQueryable().Provider.CreateQuery(query);

Without supplying the, I'm having difficulties getting this toIQueryable opposed to theGetQuery method.

I currently just have this code:

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 call to action is what's important.Expression.Call , where I was required to provide anIQueryable it would still function, but I'd want to be able to construct the phrase without mentioning an existingIQueryable .

Even so, is this possible?

Edit:
I really don't need to do this at all, now that I give it some thought. Simply passing the IQueryable as a parameter to the GetQuery function makes perfect sense. However, I'll continue to raise this query.

1
-1
12/27/2016 8:38:01 AM

Accepted Answer

It could be created as an additional expression from IQueryable to IOrderedQueryable, like this:

public Expression getOrderByQuery<T>(PropertyInfo col)
{
    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}

    var paramList = Expression.Parameter(typeof(IQueryable<T>));

    // {tempList.OrderBy(p => p.ID)}    
    var orderByMethodExpression = Expression.Call(genericOrdebyMethod, paramList, lambda); 

    return Expression.Lambda(orderByMethodExpression, paramList);
}

I use it in this manner, and my list is organized:

var tempList = new List<PlayerDTO>() 
  { 
     new PlayerDTO(2, "First"), 
     new PlayerDTO(1, "Second") 
  };

var e = (Expression<Func<IQueryable<PlayerDTO>, IOrderedQueryable<PlayerDTO>>>)
               getOrderByQuery<PlayerDTO>(typeof(PlayerDTO).GetProperty("Id"));
e.Compile().Invoke(tempList.AsQueryable()).Dump();
1
12/27/2016 7:41:14 AM


Related Questions





Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow