Building OrderBy Lambda Expression from Property Name in C#






4.92/5 (11 votes)
Let's make a lambda expression from a property name of a particular entity, and use it for OrderBy shorting
Introduction
Here in this post, we are going to see how to make a lambda expression from a property name of a particular entity, and use it for OrderBy
shorting for both IQueryable
and IEnumerable
sources.
Background
Let’s say we have a model.
public class Phone
{
public double Price { get; set; }
public string Brand { get; set; }
}
And we have a data source Db.Phones
, and for regular OrderBy
shorting by property, we use:
/*When using lambda expression*/
Db.Phones.OrderBy(x => x.Price).ToList();
Db.Phones.OrderBy(x => x.Brand).ToList();
Now, we want to do this shorting with property name only, rather than using lambda expression, like:
/*But we needed to do*/
Db.Phones.OrderBy("Price").ToList();
Db.Phones.OrderBy("Brand").ToList();
One interesting thing is the data source could be any among IQueryable
or IEnumerable
. So we have to consider both.
Db.Phones //source is IQueryable<Phone>
Db.Phones.AsEnumerable() //source is IEnumerable<Phone>
Utility Class
Here is the utility class, which will be used to make lambda expression from a property name for a particular entity.
public static class Utility
{
//makes expression for specific prop
public static Expression<Func<TSource, object>> GetExpression<TSource>(string propertyName)
{
var param = Expression.Parameter(typeof(TSource), "x");
Expression conversion = Expression.Convert(Expression.Property
(param, propertyName), typeof(object)); //important to use the Expression.Convert
return Expression.Lambda<Func<TSource, object>>(conversion, param);
}
//makes deleget for specific prop
public static Func<TSource, object> GetFunc<TSource>(string propertyName)
{
return GetExpression<TSource>(propertyName).Compile(); //only need compiled expression
}
//OrderBy overload
public static IOrderedEnumerable<TSource>
OrderBy<TSource>(this IEnumerable<TSource> source, string propertyName)
{
return source.OrderBy(GetFunc<TSource>(propertyName));
}
//OrderBy overload
public static IOrderedQueryable<TSource>
OrderBy<TSource>(this IQueryable<TSource> source, string propertyName)
{
return source.OrderBy(GetExpression<TSource>(propertyName));
}
}
Here are the two overloads for OrderBy
to handle both IEnumerable<TSource>
and IQueryable<TSource>
.
Using the Code
Now let’s test the overloads:
List<Phone> orderedByPrice = null;
List<Phone> orderedByBrand = null;
/*When source is IQueryable*/
orderedByPrice = Db.Phones.OrderBy("Price").ToList();
orderedByBrand = Db.Phones.OrderBy("Brand").ToList();
/*When source is IEnumerable*/
orderedByPrice = Db.Phones.AsEnumerable().OrderBy("Price").ToList();
orderedByBrand = Db.Phones.AsEnumerable().OrderBy("Brand").ToList();
For a quick overview, check out https://dotnetfiddle.net/sEmFzq.
Limitations
- Yes, there could be something which I misunderstood or presented. So if you find anything, just let me know.
- I have tested this for simple properties (
string Name
,int Id
, etc.) as I have shown here. But if we have complex properties like (Processor Processor;
whereprocessor
has name, and we want to doorder by Processor.Name
), it may collapse.
Find the Visual Studio 2010 solution in the attachment.