C# - code to order by a property using the property name as a string

c# order list by property name
c# sort array of objects by property
sort by object property c#
c sort list of objects by string property
the orderby call must specify property names
order by in list c#
sort list based on attribute c#
linq orderby property

What's the simplest way to code against a property in C# when I have the property name as a string? For example, I want to allow the user to order some search results by a property of their choice (using LINQ). They will choose the "order by" property in the UI - as a string value of course. Is there a way to use that string directly as a property of the linq query, without having to use conditional logic (if/else, switch) to map the strings to properties. Reflection?

Logically, this is what I'd like to do:

query = query.OrderBy(x => x."ProductId");

Update: I did not originally specify that I'm using Linq to Entities - it appears that reflection (at least the GetProperty, GetValue approach) does not translate to L2E.

I would offer this alternative to what everyone else has posted.

System.Reflection.PropertyInfo prop = typeof(YourType).GetProperty("PropertyName");

query = query.OrderBy(x => prop.GetValue(x, null));

This avoids repeated calls to the reflection API for obtaining the property. Now the only repeated call is obtaining the value.

However

I would advocate using a PropertyDescriptor instead, as this will allow for custom TypeDescriptors to be assigned to your type, making it possible to have lightweight operations for retrieving properties and values. In the absence of a custom descriptor it will fall back to reflection anyhow.

PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(YourType)).Find("PropertyName");

query = query.OrderBy(x => prop.GetValue(x));

As for speeding it up, check out Marc Gravel's HyperDescriptor project on CodeProject. I've used this with great success; it's a life saver for high-performance data binding and dynamic property operations on business objects.

Sorting using property name as string, The solution from your link uses an "Expression.Convert" which most of the time doesn't work with LINQ to Entities. Here is a working extension method: What’s the simplest way to code against a property in C# when I have the property name as a string? For example, I want to allow the user to order some search results by a property of their choice (using LINQ). They will choose the “order by” property in the UI – as a string value of course.

I'm a little late to the party, however, I hope this can be of some help.

The problem with using reflection is that the resulting Expression Tree will almost certainly not be supported by any Linq providers other than the internal .Net provider. This is fine for internal collections, however this will not work where the sorting is to be done at source (be that SQL, MongoDb, etc.) prior to pagination.

The code sample below provides IQueryable extention methods for OrderBy and OrderByDescending, and can be used like so:

query = query.OrderBy("ProductId");

Extension Method:

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

    public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> source, string propertyName)
    {
        return source.OrderByDescending(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);            
    }
}

Regards, Mark.

Linq Order By When You Have Property Name, So what we need is a way of mapping the string to a property and private static IEnumerable<T> OrderBy<T>(IEnumerable<T> entities, string propertyName) you're going to be looking for properties of the derived class using For example​, I want the list of employees whose AccountName = “Finance”. So I was wondering if there was a way I could do the OrderBy() and OrderByDescending() clauses by supplying a string for the field name something like: _Repository.GetAllList().OrderBy(r => r."SomeTextField") In this way I could move all this code to a common method. Any pointers greatly appreciated.

I liked the answer from @Mark Powell, but as @ShuberFu said, it gives the error LINQ to Entities only supports casting EDM primitive or enumeration types.

Removing var propAsObject = Expression.Convert(property, typeof(object)); didn't work with properties that were value types, such as integer, as it wouldn't implicitly box the int to object.

Using Ideas from Kristofer Andersson and Marc Gravell I found a way to construct the Queryable function using the property name and have it still work with Entity Framework. I also included an optional IComparer parameter. Caution: The IComparer parameter does not work with Entity Framework and should be left out if using Linq to Sql.

The following works with Entity Framework and Linq to Sql:

query = query.OrderBy("ProductId");

And @Simon Scheurer this also works:

query = query.OrderBy("ProductCategory.CategoryId");

And if you are not using Entity Framework or Linq to Sql, this works:

query = query.OrderBy("ProductCategory", comparer);

Here is the code:

public static class IQueryableExtensions 
{    
public static IOrderedQueryable<T> OrderBy<T>(this IQueryable<T> query, string propertyName, IComparer<object> comparer = null)
{
    return CallOrderedQueryable(query, "OrderBy", propertyName, comparer);
}

public static IOrderedQueryable<T> OrderByDescending<T>(this IQueryable<T> query, string propertyName, IComparer<object> comparer = null)
{
    return CallOrderedQueryable(query, "OrderByDescending", propertyName, comparer);
}

public static IOrderedQueryable<T> ThenBy<T>(this IOrderedQueryable<T> query, string propertyName, IComparer<object> comparer = null)
{
    return CallOrderedQueryable(query, "ThenBy", propertyName, comparer);
}

public static IOrderedQueryable<T> ThenByDescending<T>(this IOrderedQueryable<T> query, string propertyName, IComparer<object> comparer = null)
{
    return CallOrderedQueryable(query, "ThenByDescending", propertyName, comparer);
}

/// <summary>
/// Builds the Queryable functions using a TSource property name.
/// </summary>
public static IOrderedQueryable<T> CallOrderedQueryable<T>(this IQueryable<T> query, string methodName, string propertyName,
        IComparer<object> comparer = null)
{
    var param = Expression.Parameter(typeof(T), "x");

    var body = propertyName.Split('.').Aggregate<string, Expression>(param, Expression.PropertyOrField);

    return comparer != null
        ? (IOrderedQueryable<T>)query.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable),
                methodName,
                new[] { typeof(T), body.Type },
                query.Expression,
                Expression.Lambda(body, param),
                Expression.Constant(comparer)
            )
        )
        : (IOrderedQueryable<T>)query.Provider.CreateQuery(
            Expression.Call(
                typeof(Queryable),
                methodName,
                new[] { typeof(T), body.Type },
                query.Expression,
                Expression.Lambda(body, param)
            )
        );
}
}

Custom Sort by Property Name | C# Online Compiler, Custom Sort by Property Name | Test your C# code online with . using System.​Linq;. 3 private static object GetProperty(object o, string propertyName). 41. Dynamic Linq: OrderBy Using a String for a Property Name Now this is kind of dangerous to do since there is no compile time check (Like most things set in markup) but say you want to sort a collection, using the Linq extension methods, but you don’t know what you what to sort on at any given time.

Yes, I don't think there's another way than Reflection.

Example:

query = query.OrderBy(x => x.GetType().GetProperty("ProductId").GetValue(x, null));

Sort List<T> with string property names, this will sort the collection on multiple properties using lambda expression. cars.​OrderBy(c => c.Make) .ThenBy  Now, I want to be able to set the properties using a string as you could do with a DataSet object. Something like this: myClass["Name"] = "John" myClass["Address"] = "1112 River St., Boulder, CO" Ideally, I want to just assign a variable and then set the property using that string name from the variable:

query = query.OrderBy(x => x.GetType().GetProperty("ProductId").GetValue(x, null));

Trying to recall exact syntax off the top of my head but I think that is correct.

Building OrderBy Lambda Expression from Property Name in C# , Let's make a lambda expression from a property name of a particular entity, and use it for OrderBy Hide Copy Code. public class Phone { public double Price { get; set; } public string Brand { get; set; } } Now, we want to do this shorting with property name only, rather than using lambda expression, like:. What's the simplest way to code against a property in C# when I have the property name as a string? For example, I want to allow the user to order some search results by a property of their choice (using LINQ). They will choose the "order by" property in the UI - as a string value of course. Is there a way to use that string directly as a

EF.Property<TProperty>(Object, String) Method, This is useful when you want to reference a shadow state property in a LINQ query. Currently this method can C# Copy. public static TProperty Property<​TProperty> (object entity, string propertyName); static member Examples. The following code performs a filter using the a LastUpdated shadow state property. Copy. public class Phone { public double Price { get; set; } public string Brand { get; set; } } And we have a data source Db.Phones, and for regular OrderBy shorting by property, we use: /* When using lambda expression*/ Db.Phones.OrderBy(x => x.Price).ToList(); Db.Phones.OrderBy(x => x.Brand).ToList();

Type.GetProperty Method (System), For example, the String class has an indexer named Chars[]. Indexed properties created using languages other than C# can have names other than Item, as well. the number, order, and type of the parameters for the indexed property to get. By using auto-implemented properties, you can simplify your code while having the C# compiler transparently provide the backing field for you. If a property has both a get and a set accessor, both must be auto-implemented. You define an auto-implemented property by using the get and set keywords without

PropertyInfo.GetValue Method (System.Reflection), The following example defines a Planet class that has two properties: Name , the property (the indexer in C#) of the String class. C# Copy. using System; using  To order a sequence by the values of the elements themselves, specify the identity function (x => x in Visual C# or Function (x) x in Visual Basic) for keySelector. Two methods are defined to extend the type IOrderedEnumerable<TElement>, which is the return type of this method.

Comments
  • I think you'd have to use reflection, and I'm not sure you can use reflection in a lambda expression... well, almost certainly not in Linq to SQL but maybe when using Linq against a list or something.
  • @Telos: There's no reason that you can't use reflection (or any other API) in a lambda. Whether or not it will work if the code gets evaluated as an expression and translated into something else (like LINQ-to-SQL, as you suggest) is another question entirely.
  • This is why I posted a comment instead of an answer. ;) Mostly used to Linq2SQL...
  • Just had to overcome the same problem.. see my answer below. stackoverflow.com/a/21936366/775114
  • Note that reflected invocation (i.e. GetValue) is the most costly part of reflection. Metadata retrieval (i.e. GetProperty) is actually less costly (by an order of magnitude), so by caching that part, you are not really saving yourself that much. This is going to cost pretty much the same either way, and that cost is going to be heavy. Just something to note.
  • @jrista: invocation is the most costly, to be certain. However, "less costly" does not mean "free", or even close to it. Metadata retrieval takes a non-trivial amount of time, so there is an advantage to caching it and no disadvantage (unless I'm missing something here). In truth this should really be using a PropertyDescriptor anyway (to account for custom type descriptors, which could make value retrieval a lightweight operation).
  • Searched for hours for something like this to handle sorting a ASP.NET GridView programmatically: PropertyDescriptor prop = TypeDescriptor.GetProperties(typeof(ScholarshipRequest)).Find(e.SortExpression, true);
  • stackoverflow.com/questions/61635636/… Had a problem with reflection it didn't work out in EfCore 3.1.3. It seems to throw error in EfCore 2 which needs to be activated for the warnings. Use the answer of @Mark below
  • I receive the following: InvalidOperationException: The LINQ expression 'DbSet<MyObject> .Where(t => t.IsMasterData) .OrderBy(t => t.GetType().GetProperty("Address").GetValue( obj: t, index: null).GetType())' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to either AsEnumerable(), AsAsyncEnumerable(), ToList(), or ToListAsync().
  • Excellent solution - I was looking for exactly that. I really need to dig into the Expression trees. Still very rookie at that. @Mark, any solution to do nested expressions? Say I have a type T with a property "Sub" of type TSub that itself has a property "Value". Now I'd like to get the expression Expression<Func<T, object>> for the string "Sub.Value".
  • Why do we need the Expression.Convert to convert property to object? I'm getting a Unable to cast the type 'System.String' to type 'System.Object'. LINQ to Entities only supports casting EDM primitive or enumeration types. error, and removing it seems to work.
  • @Demodave if i remember correctly. var propAsObject = Expression.Convert(property, typeof(object)); and just use property in place of propAsObject
  • Gold. Adapted for a .Net Core 2.0.5.
  • Got error LINQ to Entities only supports casting EDM primitive or enumeration types