0

When I have queryable such as

var query = dbSet.AsQueryable();

and I would like to dynamically set orderBy using reflection

var orderBy = "School.Name"
query = query.OrderBy("School.Name");
var data = await query.ToListAsync()

I do have extension to support order like this using reflection as following:

public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> source, string propertyName)
{
    return source.OrderBy(ToLambda<T>(propertyName));
}

private static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{    
    var parameter = Expression.Parameter(typeof(T));
    var property = Expression.Property(parameter, propertyName);
    var propAsObject = Expression.Convert(property, typeof(object));

    return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
}

Problem is to create lambda for inner object property such as School.Name. This solution works for Name attribute on Dbset object, but not on joined.

Goal is to modify ToLambda method to support joinned or inners properties.

using

query.OrderBy("School.Name"); 
// instead of 
query.OrderBy(m => m.School.Name );
James Z
  • 12,209
  • 10
  • 24
  • 44
Jaroslav Langer
  • 131
  • 1
  • 12
  • You can check [my realization](https://stackoverflow.com/a/65850085/10646316) of dynamic ordering. Also check `MakePropPath`, which you can reuse in your method. – Svyatoslav Danyliv Nov 01 '22 at 11:20

1 Answers1

0

I have solved it as following:

private static Expression<Func<T, object>> ToLambda<T>(string propertyName)
{
    if (propertyName.Contains('.'))
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = NestedProperty(parameter, propertyName.Split('.'));
        var propAsObject = Expression.Convert(property, typeof(object));

        return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
    }
    else
    {
        var parameter = Expression.Parameter(typeof(T));
        var property = Expression.Property(parameter, propertyName.ToLower());
        var propAsObject = Expression.Convert(property, typeof(object));

        return Expression.Lambda<Func<T, object>>(propAsObject, parameter);
    }
    
}
private static MemberExpression NestedProperty(Expression propertyHolder, params string[] propertyPath)
{
    MemberExpression memberExpression = Expression.Property(propertyHolder, propertyPath[0]);

    foreach (var member in propertyPath.Skip(1))
    {
        memberExpression = Expression.Property(memberExpression, member);
    }

    return memberExpression;
}
Jaroslav Langer
  • 131
  • 1
  • 12