Create an OrderBy Expression for LINQ/Lambda
Asked Answered
F

2

20

I'm creating a proof of concept that uses Lambda/LINQ for dynamic where and orderby. The following code works for the where expression, but I can not figure out how to create an order by expression. For this example, if possible I would like to keep it simple; I would rather not write code that modifies an Expression Tree.

void Main()
{
    DateTime productSince = DateTime.UtcNow.Subtract(new TimeSpan(1,30,0));
    Expression<Func<Products, bool>> filter = d => d.CreatedDate > productSince && d.Price < 100 ;    
    List<Products> products = GetProducts(filter, Products);
    Console.WriteLine(products);
}

private static List<Products> GetProducts(Expression<Func<Products, bool>> filter,  Table<Products> Products)
{

    var products = Products.Where(filter);
    return products.ToList();
}

What I want is similar to the following but can not figure out the code to create the order by expression.

void Main()
{
    DateTime productSince = DateTime.UtcNow.Subtract(new TimeSpan(1,30,0));
    Expression<Func<Products, bool>> filter = d => d.CreatedDate > productSince && d.Price < 100 ;
    Expression<Func<Products, ????>> orderBy = d => ??????;

    List<Products> products = GetProducts(filter, orderBy, Products);
    Console.WriteLine(products);
}

private static List<Products> GetProducts(Expression<Func<Products, bool>> filter,
               Expression<Func<Products, ???>> orderBy, Table<Products> Products)
{

    var products = Products.Where(filter).OrderBy(orderBy);
    return products.ToList();
}

If you are wondering, I'm using LinqPad for this proof of concept.

Freyah answered 23/4, 2011 at 18:58 Comment(0)
M
26
private static List<Products> GetProducts<TOrderBy>(Expression<Func<Products, bool>> filter,
               Expression<Func<Products, TOrderBy>> orderBy, Table<Products> Products)
{

    var products = Products.Where(filter).OrderBy(orderBy);
    return products.ToList();
}

If you look at OrderBy extension method it accepts a Expression<Func<T, TOrderBy>> because the expression can result in any type depending

.OrderBy(x => x.ID) // <T, int>
.OrderBy(x => x.Name) // <T, string>

So therefor your wrapper method needs to be able to accept that generic type to pass in.

Messinger answered 23/4, 2011 at 19:2 Comment(4)
Thanks for the answer, but how do I reference TOrderBy?Freyah
You don't, it's used by the orderBy parameter. Expression<Func<Products, TOrderBy>> orderByMessinger
To help others out. To create orderBy expression do something like Expression <Func<Products, decimal>> orderBy = d => d.Price;. Where Price is a decimal type. In the previous code, decimal could be any type, such as DateTime, string, or int. This type needs to match the type returned from the expresion. If DateTime is used, then the lambda expression should be something like d.CreatedDate.Freyah
Correct. The reason my code works is because the method accepts a <TOrderBy> generic parameter type which is inferred by the parameter passed into the orderBy.Messinger
T
12

what you are looking for is:

Expression<Func<Products, dynamic>>;

try create a structure/class to hold both the Expression and if it is ascending or descending.

Turanian answered 21/11, 2012 at 14:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.