Reputation: 21
At first I was using:
sortedList = unsorted.AsParallel().OrderBy(myItem => TypeDescriptor.GetProperties(myItem)[firstSort.Item2].GetValue(myItem));
Where firstSort.Item2 was the string name of the property. However, the performance degraded significantly as the number of items in the unsorted list increased. (As I expected)
Is there a way to do this without using reflection?
The brute force approach would be to do something like:
if(firstSort.Item2 == "Size")
sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Size);
else if(firstSort.Item2 == "Price")
sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Price);
...
I'm looking for something that would accomplish the above behavior, but without having to hardcode in all the different properties in the interface.
Upvotes: 2
Views: 6130
Reputation: 31799
You can use the DLR. The open source framework Impromptu-Interface does all the dlr plumbing behind the scenes and and gets the value of a property 2.5x faster than reflection.
sortedList = unsorted.AsParallel().OrderBy(myItem => Impromptu.InvokeGet(myItem,firstSort.Item2));
Upvotes: 0
Reputation: 40393
I like Roger's answer the best for a true solution, but if you want something simple, you can build a small code generator to take the class and break out its properties into a dictionary of string to lambda, representing each property. At runtime, you could call from this dictionary to retrieve the appropriate lambda.
Upvotes: 0
Reputation: 2044
You can create the PropertyInfo once and use it to call GetValue over multiple target objects. This will be much less expensive than calling TypeDescriptor.GetProperties for every item in the list.
Also, try removing AsParallel - the overhead may actually be reducing performance rather than helping it in this case.
Try this:
var prop = unsorted.GetType().GetGenericArguments()[0].GetProperty(firstSort.Item2);
sortedList = unsorted.OrderBy(myItem => prop.GetValue(myItem, null));
Upvotes: 1
Reputation: 453
Your best bet is to use the Dynamic LINQ library provided by Microsoft.
Here is a link: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
Upvotes: 0
Reputation: 91825
You can use Expression<T>
to pre-compile the expressions that you're passing to OrderBy
. Then you can look them up at runtime.
Upvotes: 3
Reputation: 5439
If you implement ICustomTypeDescriptor in your class, then you can avoid the reflection when using TypeDescriptor.
Of course, I'm assuming you own the type of myItem
.
Upvotes: 0
Reputation: 161773
Everything you use that doesn't involve a hard-coded list of actual properties, will be using Reflection "behind the scenes".
Upvotes: 2