Reflection.Emit лучше, чем GetValue & amp; SetValue: S
-
05-07-2019 - |
Вопрос
Мне сказали использовать Reflection.Emit вместо PropertyInfo.GetValue / SetValue, потому что так быстрее. Но я действительно не знаю, что из Reflection.Emit и как его использовать для замены GetValue и SetValue. Кто-нибудь может мне помочь с этим?
Решение
Просто альтернативный ответ; если вам нужна производительность, но похожий API - рассмотрите HyperDescriptor ; он использует Reflection.Emit
снизу (так что вам не нужно), но выставляет себя в API PropertyDescriptor
, так что вы можете просто использовать:
PropertyDescriptorCollection props = TypeDescriptor.GetProperties(obj);
props["Name"].SetValue(obj, "Fred");
DateTime dob = (DateTime)props["DateOfBirth"].GetValue(obj);
Одна строка кода, чтобы включить его, и он обрабатывает все кэширование и т. д.
Другие советы
Если вы выбираете / устанавливаете одно и то же свойство много раз, то использование чего-либо для создания безопасного типа действительно будет быстрее, чем отражение. Однако я бы предложил использовать Delegate.CreateDelegate
вместо Reflection.Emit. Это легче сделать правильно, и это все еще невероятно быстро.
Я использовал это в своей реализации буферов протокола, и это имело огромное значение по сравнению с PropertyInfo.GetValue / SetValue
. Как уже говорили другие, делайте это только после того, как докажете, что самый простой способ слишком медленный.
У меня есть сообщение в блоге с более подробной информацией, если вы решите пойти по маршруту CreateDelegate
.
Использовать PropertyInfo.GetValue / SetValue
Если у вас есть проблемы с производительностью, кэшируйте объект PropertyInfo (не вызывайте GetProperty повторно)
Если - и только если - использование отражения является узким местом производительности вашего приложения (как видно в профилировщике), используйте Delegate.CreateDelegate
Если - и действительно действительно только если - вы абсолютно уверены, что чтение / запись значений по-прежнему является наихудшим узким местом, пришло время начать знакомство с увлекательным миром генерации IL во время выполнения.
Я действительно сомневаюсь, что это того стоит, каждый из этих уровней увеличивает сложность кода в большей степени, чем повышает производительность - делайте это только в случае необходимости.
И если доступ к свойствам во время выполнения - это ваше узкое место в производительности, то, вероятно, лучше использовать доступ во время компиляции (трудно одновременно быть и универсальной, и сверхвысокой производительностью).
Назначение Reflection.Emit полностью отличается от PropertyInfo.Get / SetValue. С помощью Reflection.Emit вы можете напрямую генерировать код IL, например, в динамически скомпилированные сборки и выполнять этот код. Конечно, этот код может получить доступ к вашим свойствам.
Я серьезно сомневаюсь, что это будет намного быстрее, чем в конце концов использовать PropertyInfo, и для этого он тоже не предназначен. Например, вы можете использовать Reflection.Emit в качестве генератора кода для небольшого компилятора.
Использование Reflection.Emit кажется слишком "умным", а также преждевременной оптимизацией. Если вы профилируете свое приложение и обнаружите, что отражение GetValue / SetValue является узким местом, тогда вы можете подумать об оптимизации, но, вероятно, даже тогда ...