Order a list by a property name(string value)?

前端 未结 2 1955
余生分开走
余生分开走 2020-12-28 10:45

I have a list of objects. How can I order this list using property name?

string orderbyField = \"Code\";
List l = FillList();
l =          


        
                      
相关标签:
2条回答
  • 2020-12-28 10:52

    If you don't have to provide the property name as a string, it's pretty simple using dynamic:

    List<object> l = FillList();
    l = l.OrderBy(o => ((dynamic)o).Id);
    

    If the property name has to be a string, then it gets more a bit complicated but can be done using reflection (although it is not very efficient):

    l = l.OrderBy(o => o.GetType()
                        .GetProperty("Code")
                        .GetValue(o, null));
    

    You should also think about adding some error handling, e.g. if the property doesn't exist.

    Also, if all the elements in the list have same runtime type, then it would be much more efficient to compile a getter function using expression trees and reusing it (instead of directly using reflection).

    public static Func<object, object> CreateGetter(Type runtimeType, string propertyName)
    {
        var propertyInfo = runtimeType.GetProperty(propertyName);
    
        // create a parameter (object obj)
        var obj = Expression.Parameter(typeof(object), "obj");  
    
        // cast obj to runtimeType
        var objT = Expression.TypeAs(obj, runtimeType); 
    
        // property accessor
        var property = Expression.Property(objT, propertyInfo); 
    
        var convert = Expression.TypeAs(property, typeof(object));
        return (Func<object, object>)Expression.Lambda(convert, obj).Compile();
    }
    

    and use it like:

    var codeGetter = CreateGetter(l[0].GetType(), "Code"); // using the 1st element as an example
    l = l.OrderBy(o => codeGetter(o));
    
    0 讨论(0)
  • 2020-12-28 11:11

    Order by property name without type reflection

        public static class IQueryableExtensions
        {
          public static IQueryable<T> OrderBy<T>(this IQueryable<T> source, string 
          propertyName)
          {
          return (IQueryable<T>)OrderBy((IQueryable)source, propertyName);
          }
    
          public static IQueryable OrderBy(this IQueryable source, string propertyName)
          {
            var x = Expression.Parameter(source.ElementType, "x");
            var body = propertyName.Split('.').Aggregate<string, Expression>(x, 
            Expression.PropertyOrField);
    
            var selector = Expression.Lambda
             (Expression.PropertyOrField(x, propertyName), x);
    
             return source.Provider.CreateQuery(
                Expression.Call(typeof(Queryable), "OrderBy", new Type[] { 
                 source.ElementType, selector.Body.Type },
                     source.Expression, selector
                     ));
          }
    
          public static IQueryable<T> OrderByDescending<T>(this IQueryable<T> source, 
          string propertyName)
          {
            return (IQueryable<T>)OrderByDescending((IQueryable)source, propertyName);
          }
    
          public static IQueryable OrderByDescending(this IQueryable source, string 
          propertyName)
          {
            var x = Expression.Parameter(source.ElementType, "x");
            var selector = Expression.Lambda(Expression.PropertyOrField(x, 
            propertyName),x);
            return source.Provider.CreateQuery(
                Expression.Call(typeof(Queryable), "OrderByDescending", new Type[] { 
                 source.ElementType, selector.Body.Type },
                     source.Expression, selector
                     ));
          }
    }
    
    0 讨论(0)
提交回复
热议问题