tags:

views:

212

answers:

2
public class Person
{
    public string name { get; set; }
    public Email email { get; set; }

}

public class Email
{
    public string desc { get; set; }
}

public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
{            
    var param = Expression.Parameter(typeof(T), string.Empty);
    try
    {
        var property   = Expression.Property(param, sortExpression);
        var sortLambda = Expression.Lambda<Func<T, object>>(Expression.Convert(property, typeof(object)), param);

        if (desc)
        {
            return source.AsQueryable<T>().OrderByDescending<T, object>(sortLambda);
        }

        return source.AsQueryable<T>().OrderBy<T, object>(sortLambda);
    }
    catch (ArgumentException)
    {
        return source;
    }
}

        List<Person> vet = new List<Person>();

        Person p = new Person { name = "aaa", email = new Email { desc = "[email protected]" } };
        Person pp = new Person { name = "bbb", email = new Email { desc = "[email protected]" } };
        vet.Add(p);
        vet.Add(pp);

        vet.Sort("name",true); //works
        vet.Sort("email.desc",true) // doesnt work


someone can help me?

+2  A: 

You might want to think about another method that takes a custom Comparer object to do the comparison. You could then write a custom Comparer for Person that compares them based on their email addresses.

Justin Niessner
+1  A: 

If you want this functionality look into an article by ScottGu on the Dynamic Linq Library. I believe it will do what you want.

While Lambda's are type safe there are times when you might want to generate on the fly the query as opposed to having every possible combination that a user can sort for example.

Edit

I fixed your method. Basically you need to create an expression for each member access.

 public static IEnumerable<T> Sort<T>(this IEnumerable<T> source, string sortExpression, bool desc)
    {
        var param = Expression.Parameter(typeof(T), string.Empty);
        try
        {
            var fields = sortExpression.Split('.');
            Expression property = null;
            Expression parentParam = param;
            foreach (var field in fields)
            {
                property = Expression.Property(parentParam, field);
                parentParam = property;

            }

            var sortLambda = 
                Expression.Lambda<Func<T, object>>(
                  Expression.Convert(property, typeof(object)), param);

            if (desc)
            {
                return source.AsQueryable<T>().
                     OrderByDescending<T, object>(sortLambda);
            }

            return source.AsQueryable<T>().
                 OrderBy<T, object>(sortLambda);
        }
        catch (ArgumentException)
        {
            throw;
        }
    }
JoshBerke