mercredi 22 mai 2019

C# order List of Parent objects by Child's property via Reflection

I have a method that orders a queryable by a property via reflection, like so:

   public static IQueryable<TEntity> OrderBy<TEntity>(this IQueryable<TEntity> source, string orderByProperty, bool desc)
   {
       string command = desc ? "OrderByDescending" : "OrderBy";
       var parts = orderByProperty.Split('.');
       var parameter = Expression.Parameter(typeof(TEntity), "p");
       Expression body = parameter;
       if (parts.Length > 1)
       {
           for (var i = 0; i < parts.Length - 1; i++)
           {
               body = Expression.Property(body, parts[i]);
           }
       }

       body = Expression.Property(body, property.Name);
       var orderByExpression = Expression.Lambda(body, parameter);
       resultExpression = Expression.Call(typeof(Queryable), command, 
                                       new Type[] { typeof(TEntity), property.PropertyType },
                                       source.Expression, Expression.Quote(orderByExpression));
       return source.Provider.CreateQuery<TEntity>(resultExpression);
   }

And it works if I use it for the object's properties or its children's properties, but it doesn't work when a child property is a List.

    // Success
    db.Users.OrderBy("Name", true)
    db.Users.OrderBy("CurrentAddress.City.Name", false)

    // Fail
    db.Users.OrderBy("PhoneLines.RenewalDate", true)

My model is like so:

    public class User {
        public string Name { get; set; }
        public Address CurrentAddress{ get; set; }
        public List<Phone> PhoneLines { get; set; }
    }

And I am trying to do something like this work:

    db.Users.OrderByDescending(x => 
        x.PhoneLines
          .OrderByDescending(y => y.RenewalDate)
          .Select(y => y.RenewalDate).FirstOrDefault()
    );

Right now I am only interested in making this work for first level List children, that is, I am not concerned about a cascading list scenario, just one child in the chain is a list.

Is it possible to achieve this via reflection?





Aucun commentaire:

Enregistrer un commentaire