OrderBy with StringSelector

I have the following function that retrieves me various values ​​based on the properties of an object, here Client.

public List<DistinctValue> GetDistinctValues(string propertyName) { //how should I specify the keySelector ? Func<string, object> keySelector = item => propertyName; var list = new List<DistinctValue>(); var values = this.ObjectContext.Clients.Select(CreateSelectorExpression (propertyName)).Distinct().OrderBy(keySelector); int i = 0; foreach (var value in values) { list.Add(new DistinctValue() { ID = i, Value = value }); i++; } return list; } private static Expression<Func<Client, string>> CreateSelectorExpression (string propertyName) { var paramterExpression = Expression.Parameter(typeof(Client)); return (Expression<Func<Client, string>>)Expression.Lambda( Expression.PropertyOrField(paramterExpression, propertyName), paramterExpression); } public class DistinctValue { [Key] public int ID { get; set; } public string Value { get; set; } } 

I do this because I don’t know to what property values ​​I will need to extract. It works, the result is not sorted.

Could you help me fix the sorting to make OrderBy work as expected?

Properties are strings, and I don't need to bind the sort. I also do not need to specify sort order.

Thanks a lot in advance, John.

+4
source share
2 answers

Currently keySelector returns the same string for each (property name); and since LINQ is usually stable, this does not lead to a general change. Since you have already projected onto string values, you can simply use the trivial mapping x=>x here:

 var values = this.ObjectContext.Clients.Select( CreateSelectorExpression(propertyName)).Distinct().OrderBy(x => x); 

order the items themselves.

+7
source

Thank you for the elegant solution. Next, I extended the CreateSelectorExpression method, so it can be used outside of the Client class in the above example.

 public static Expression<Func<T, string>> CreateSelectorExpression<T>(string propertyName) { var paramterExpression = Expression.Parameter(typeof(T)); return (Expression<Func<T, string>>)Expression.Lambda(Expression.PropertyOrField(paramterExpression, propertyName), paramterExpression); } 

Using

 Func<IQueryable<YourEntity>, IOrderedQueryable<YourEntity>> orderBy = o => o.OrderByDescending(CreateSelectorExpression<YourEntity>("Entity Property Name")); 
+4
source

Source: https://habr.com/ru/post/1335087/


All Articles