2009-11-26 2 views
16

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

+2

А? Reflection.Emit позволяет вам создавать код «на лету» для последующего исполнения. Но он также более сложный и подверженный ошибкам, не говоря уже о том, что трудно отлаживать.Вам нужно описать, что вы пытаетесь сделать с GetValue/SetValue, и с какими требованиями к производительности. Почему вы используете Reflection в первую очередь? –

+1

Я предполагаю, что у него есть некоторые динамически загруженные объекты и он хочет получить доступ к свойству, и вопрос в том, будет ли вызов GetValue/SetValue или * генерации IL-кода для доступа к свойству «жестко закодированный» *, будет лучше. Я предлагаю попробовать с Reflection.Emit.DynamicMethod, а затем просто проверять, какой из них быстрее. Для меня GetValue/SetValue было достаточно, мне просто нужно было генерировать IL-код для обработки событий с сигнатурами, которые неизвестны во время компиляции :) – OregonGhost

+0

I user reflection для получения и установки значений свойств объектов (я не знаю типа объектов) – Omu

ответ

26

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

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

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

+0

Что вы подразумеваете под «использованием HyperDescriptor для загрузки "? Мне просто нужно получить свойства, получить и установить для них значения, вот и все – Omu

+0

Я имею в виду, что вам нужно загрузить компонент HyperDescriptor из codeproject и включить его, как показано на странице (несколько разных способов). * Без * HyperDescriptor это прославленное отражение; HyperDescriptor перехватывает TypeDescriptor и заменяет код отражения динамическим IL. –

+1

Это сбивает с толку, я согласен; тот же код отлично работает с/без HyperDescriptor, но он/много/(~ 100x) медленнее. Любые проблемы с его работой, дайте мне знать (это было несколько лет назад, когда я это написал, но я все еще помню большую часть этого!) –

1

Цель Reflection.Emit полностью отличается от цели PropertyInfo.Get/SetValue. Via Reflection.Emit, вы можете напрямую испускать IL-код, например, в динамически скомпилированные сборки и выполнять этот код. Конечно, этот код может получить доступ к вашим свойствам.

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

1

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

11

Использование PropertyInfo.GetValue/SetValue

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

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

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

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

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

+0

Но выполнимо: http: // www. codeproject.com/KB/cs/HyperPropertyDescriptor.aspx –

22

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

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

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

+0

Очень интересно - я попытался создать делегат в FieldInfo.SetValue, и он абсолютно ничего не изменил. На самом деле это очень очевидно, так как все, что я делал, это изменить способ вызова функции, и это сама функция медленна. Итак, как вы получили это увеличение производительности? Мне не повезло найти информацию об этом в вашем сообщении в блоге (возможно, я просто слепой :-D) – Steffen

+0

Просто перечитайте свою запись в блоге и заметите, что часть GetGetMethod и GetSetMethod, по-видимому, я * раньше был слепым. В любом случае, это явно объясняет разницу в скорости, однако для FieldInfos я все еще в неведении: -S Я, однако, с нетерпением жду примера Marcs :-) Просто хотел сообщить, что я узнал, что вы сделали ускорить работу делегатов. – Steffen

+1

Cheers (+1) - Я просто использовал эту идею, чтобы сохранить .1s - .8s на страницу по некоторым отраженным населенным классам :-) – Keith