Reflection.Emit лучше, чем GetValue и SetValue: S - PullRequest
16 голосов
/ 26 ноября 2009

Мне сказали использовать Reflection.Emit вместо PropertyInfo.GetValue / SetValue, потому что так быстрее. Но я действительно не знаю, что из Reflection.Emit и как его использовать для замены GetValue и SetValue. Кто-нибудь может мне помочь с этим?

Ответы [ 5 ]

26 голосов
/ 26 ноября 2009

просто альтернативный ответ; если вам нужна производительность, но похожий API - рассмотрите HyperDescriptor ; он использует Reflection.Emit снизу (так что вам не нужно), но выставляет себя на PropertyDescriptor API, поэтому вы можете просто использовать:

PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj);
props["Name"].SetValue(obj, "Fred");
DateTime dob = (DateTime)props["DateOfBirth"].GetValue(obj);

Одна строка кода, чтобы включить его, и он обрабатывает все кэширование и т. Д.

22 голосов
/ 26 ноября 2009

Если вы выбираете / устанавливаете одно и то же свойство много раз, то использование чего-либо для создания безопасного типа действительно будет быстрее, чем отражение. Однако я бы предложил использовать Delegate.CreateDelegate вместо Reflection.Emit. Это легче сделать правильно, и это все еще невероятно быстро.

Я использовал это в своей реализации Protocol Buffers, и это имело огромное значение по сравнению с PropertyInfo.GetValue/SetValue. Как уже говорили другие, делайте это только после того, как докажете, что самый простой способ слишком медленный.

У меня есть сообщение в блоге с более подробной информацией, если вы решите пойти по маршруту CreateDelegate.

11 голосов
/ 26 ноября 2009

Использовать PropertyInfo.GetValue / SetValue

Если у вас есть проблемы с производительностью, кешируйте объект PropertyInfo (не вызывайте GetProperty несколько раз)

Если - и только если - использование отражения является узким местом производительности вашего приложения (как видно в профилировщике), используйте Delegate.CreateDelegate

Если - и действительно действительно только если - вы абсолютно уверены, что чтение / запись значений по-прежнему является наихудшим узким местом, пришло время начать изучение забавного мира генерации IL во время выполнения.

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

И если доступ к свойствам во время выполнения - это ваше узкое место в производительности, то, вероятно, лучше использовать доступ во время компиляции (трудно одновременно быть универсальной и сверхвысокой производительностью).

1 голос
/ 26 ноября 2009

Использование Reflection.Emit кажется слишком «умным», а также преждевременной оптимизацией. Если вы профилируете свое приложение и обнаружите, что отражение GetValue / SetValue является узким местом, то вы можете подумать об оптимизации, но, вероятно, даже тогда ...

1 голос
/ 26 ноября 2009

Назначение Reflection.Emit полностью отличается от PropertyInfo.Get / SetValue. С помощью Reflection.Emit вы можете напрямую генерировать код IL, например, в динамически скомпилированные сборки и выполнять этот код. Конечно, этот код может получить доступ к вашим свойствам.

Я серьезно сомневаюсь, что это будет намного быстрее, чем в конце концов использовать PropertyInfo, и это тоже не для этой цели. Например, вы можете использовать Reflection.Emit в качестве генератора кода для небольшого компилятора.

...