Alex Rivera | Logout

Access nested properties with dynamic lambda using Linq.Expression

Asked 2009-11-04T14:21:18.547
10

Let's assume that I have two classes:

class person
{
    int ID
    string name
    Address address
}
class address
{
    int ID
    string street
    string country
}

These classes are more or less given, they are mapped via nHibernate to be honest :)

In a grid (datatables.net as base) I would like to have a type-independent sorting.

Therefore I created a lambda expression:

  var param = Expression.Parameter(typeof(T), typeof(T).Name);
  var sortExpression = Expression.Lambda<Func<T, object>>
                              (Expression.Convert(Expression.Property(param, "Property to sort"), typeof(object)), param);

If I pass Person as Type T and replace the "Property to sort" with "name" it works fine (creates a correct lambda). If the Property to sort is "address.street" it won't work, throw me the following error:

Property 'address.street' is not defined for type 'person'

I see only one solution so far, but not clear enough... I would try to split the string which contains the Property-Name (split by .)

Can anyone give a better solution? I need to add the sortExpression to an IQueryable object query.OrderBy(sortExpression).

Not sure if my title is clear, please go ahead and correct it.

Thanks in advance.

Edit
Report

1 Answer

0

Try this one

    public static IQueryable<T> SortIQueryable<T>(IQueryable<T> data, string fieldName, string sortOrder)
    {
        if (string.IsNullOrWhiteSpace(fieldName)) return data;
        if (string.IsNullOrWhiteSpace(sortOrder)) return data;

        var param = Expression.Parameter(typeof(T), "i");

        MemberExpression property = null;
        string[] fieldNames = fieldName.Split('.');
        foreach (string filed in fieldNames)
        {
            if (property == null)
            {
                property = Expression.Property(param, filed);
            }
            else
            {
                property = Expression.Property(property, filed);
            }
        }

        Expression conversion = Expression.Convert(property, typeof(object));//Expression.Property(param, fieldName)
        var mySortExpression = Expression.Lambda<Func<T, object>>(conversion, param);

        return (sortOrder == "desc") ? data.OrderByDescending(mySortExpression)
            : data.OrderBy(mySortExpression);
    }
answered 2013-05-24T04:39:18.740

Your Answer