Chris
Chris

Reputation: 21

How can I access a property dynamically by name without using reflection?

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

Answers (7)

jbtule
jbtule

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

Joe Enos
Joe Enos

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

Misko
Misko

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

justin
justin

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

Roger Lipscombe
Roger Lipscombe

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

davisoa
davisoa

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

John Saunders
John Saunders

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

Related Questions