Pages

Friday, April 27, 2018

How to OrderBy with the property name using LINQ?

In this post we are gonna re-invent the LINQ's OrderBy extension method.
The implementation of OrderBy allows us to pass lambda expression in the form: x => x.Name
so to order list of students by name, you do the following:
var orderedStudents = allStudents.OrderBy(s => s.Name);
but what if you want to order dynamically by the property name ("Name") in run-time (from data storage source for example)
what would you do, do you use switch-case?
Nah, there's a much more better solution than this and it's 3~5 lines of code!

Lambda Expressions

We need the lambda expression to be replaced by a string parameter, fortunately it's easy building up a lambda expression by the property name and the object type.

Let's break down the lambda expression passed to OrderBy : x => x.Name
x is the parameter and it's of type T which get inferred in compile time from the invoked list.
Name is the member

so let's create them:

Parameter:
        var param = Expression.Parameter(typeof(Foo), "p");
Member:
        var member = Expression.Property(param, "Name");
then assemble the lambda expression:
        var lambda = Expression.Lambda<Func<Foo, object>>(member, param);
lambda will only work on IQueryable because it's of type Expression<Func<Foo, object>>
to work on IEnumerable we need to compile it:
         lambda.Compile();

the following is the complete code:

public static class NiceLinq
{
public static IEnumerable<T> OrderBy<T>(this IEnumerable<T> notOrderedList, string propertyName)
{
var lambda = GetLambda<T>(propertyName);
var orderedList = notOrderedList.OrderBy(lambda);
return orderedList;
}
private static Func<T, object> GetLambda<T>(string propertyName)
{
var param = Expression.Parameter(typeof(T), "p");
var member = Expression.Property(param, propertyName);
Expression conversion = Expression.Convert(member, typeof(object)); //explicit casting is a must
var lambda = Expression.Lambda<Func<T, object>>(conversion, param);
return lambda.Compile();
}
}
public class Program
{
public static void Main(String[] args)
{
//some code from data storage source
var orderedStudents = allStudents.OrderBy("Name");
}
}
view raw OrderBy.cs hosted with ❤ by GitHub





No comments:

Post a Comment

Note: Only a member of this blog may post a comment.

Dynamically load jndi.properties when JMeter is running

An approach to having all test configurations in one place is using the jndi.properties file of JMeter. When maintaining many JMeter test su...