Как я могу получить доступ к свойству динамически по имени без использования отражения? - PullRequest
2 голосов
/ 18 февраля 2011

Сначала я использовал:

sortedList = unsorted.AsParallel().OrderBy(myItem => TypeDescriptor.GetProperties(myItem)[firstSort.Item2].GetValue(myItem));

Где firstSort.Item2 - строковое имя свойства. Однако производительность значительно снизилась, так как количество элементов в несортированном списке увеличилось. (Как я и ожидал)

Есть ли способ сделать это без использования отражения?

Подход грубой силы должен был сделать что-то вроде:

if(firstSort.Item2 == "Size")
   sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Size);
else if(firstSort.Item2 == "Price")
   sortedList = unsorted.AsParallel().OrderBy(myItem => myItem.Price);
...

Я ищу что-то, что могло бы выполнить вышеуказанное поведение, но без необходимости жестко кодировать все различные свойства интерфейса.

Ответы [ 7 ]

3 голосов
/ 18 февраля 2011

Вы можете использовать Expression<T> для предварительной компиляции выражений, которые вы передаете OrderBy. Затем вы можете посмотреть их во время выполнения.

2 голосов
/ 18 февраля 2011

Все, что вы используете, что не связано с жестко заданным списком реальных свойств, будет использовать Reflection "за кулисами".

1 голос
/ 18 февраля 2011

Вы можете создать PropertyInfo один раз и использовать его для вызова GetValue для нескольких целевых объектов.Это будет намного дешевле, чем вызов TypeDescriptor.GetProperties для каждого элемента в списке.

Кроме того, попробуйте удалить AsParallel - накладные расходы могут фактически снизить производительность, а не помочь ей в этом случае.

Попробуйте это:

var prop = unsorted.GetType().GetGenericArguments()[0].GetProperty(firstSort.Item2);
sortedList = unsorted.OrderBy(myItem => prop.GetValue(myItem, null));
0 голосов
/ 21 апреля 2011

Вы можете использовать DLR. Фреймворк с открытым исходным кодом Impromptu-Interface выполняет всю сантехнику за кадром и получает значение свойства в 2,5 раза быстрее, чем отражение .

sortedList = unsorted.AsParallel().OrderBy(myItem => Impromptu.InvokeGet(myItem,firstSort.Item2));
0 голосов
/ 18 февраля 2011

Мне больше всего нравится ответ Роджера для истинного решения, но если вы хотите что-то простое, вы можете создать небольшой генератор кода, чтобы взять класс и разбить его свойства в словарь строк в лямбду, представляющий каждое свойство.Во время выполнения вы можете позвонить из этого словаря, чтобы получить соответствующую лямбду.

0 голосов
/ 18 февраля 2011

Лучше всего использовать библиотеку Dynamic LINQ, предоставленную Microsoft.

Вот ссылка: http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx

0 голосов
/ 18 февраля 2011

Если вы реализуете ICustomTypeDescriptor в своем классе, тогда вы можете избежать отражения при использовании TypeDescriptor.

Конечно, я предполагаю, что вы владеете типом myItem.

...