Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Building OrderBy Lambda Expression from Property Name in C#

0.00/5 (No votes)
10 Sep 2014 1  
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

  1. Yes, there could be something which I misunderstood or presented. So if you find anything, just let me know.
  2. 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; where processor has name, and we want to do order by Processor.Name), it may collapse.

Find the Visual Studio 2010 solution in the attachment.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here