2009-11-26 18 views
16

Me han dicho que use Reflection.Emit en lugar de PropertyInfo.GetValue/SetValue porque es más rápido de esta manera. Pero realmente no sé qué cosas de Reflection.Emit y cómo usarlo para sustituir GetValue y SetValue. Puede alguien ayudarme con esto ?Reflection.Emit better than GetValue & SetValue: S

+2

¿Eh? Reflection.Emit le permite crear código sobre la marcha para su posterior ejecución. Pero también es más complejo y propenso a errores, por no mencionar difícil de depurar.Debe describir lo que está tratando de hacer con GetValue/SetValue y con qué requisitos de rendimiento. ¿Por qué estás usando Reflection en primer lugar? –

+1

Supongo que tiene algunos objetos cargados dinámicamente y quiere acceder a la propiedad, y la pregunta es si llamar a GetValue/SetValue o * generar código IL para acceder a la propiedad "hard-coded" * sería lo mejor. Sugeriría probar con Reflection.Emit.DynamicMethod, y luego simplemente ver cuál es más rápido. Para mí, GetValue/SetValue era suficiente, solo necesitaba generar código IL para manejar eventos con firmas que se desconocen en tiempo de compilación :) – OregonGhost

+0

I reflexión del usuario para Obtener y establecer valores en Propiedades de objetos (no sé el tipo de los objetos) – Omu

Respuesta

26

Simplemente una respuesta alternativa; si desea el rendimiento, pero una API similar, considere HyperDescriptor; Este utiliza Reflection.Emit debajo (por lo que no tiene que hacerlo), pero se expone en la API PropertyDescriptor, por lo que sólo puede utilizar:

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

una línea de código que le permita, y que se encarga de todo el almacenamiento en caché, etc.

+0

¿Qué quiere decir con "usar HyperDescriptor por la descarga"? "¿?" solo necesito obtener propiedades, obtener y establecer valores para ellos, eso es todo – Omu

+0

Quiero decir que necesitas descargar el componente HyperDescriptor desde codeproject y habilitarlo como se muestra en la página (de diferentes maneras). * Sin * HyperDescriptor esto es una reflexión glorificada; HyperDescriptor intercepta TypeDescriptor y reemplaza el código de reflexión con IL dinámico. –

+1

Es confuso, estoy de acuerdo; el mismo código funciona bien con/sin HyperDescriptor, pero es/mucho/(~ 100x) más lento sin. Cualquier problema para que funcione, házmelo saber (¡fue hace unos años cuando lo escribí, pero aún recuerdo la mayor parte!) –

1

El propósito de Reflection.Emit es completamente diferente al de PropertyInfo.Get/SetValue. A través de Reflection.Emit, puede emitir código IL directamente, por ejemplo en ensamblados compilados dinámicamente, y ejecutar este código. Por supuesto, este código podría acceder a sus propiedades.

Tengo serias dudas de que esto sea mucho más rápido que usar PropertyInfo al final, y tampoco está hecho para este propósito. Podría usar Reflection.Emit como el generador de código para un pequeño compilador, por ejemplo.

1

El uso de Reflection.Emit parece demasiado "inteligente", así como una optimización prematura. Si un perfil de su aplicación, y te encuentras con que el/Reflexión FijarValor GetValue es el cuello de botella, entonces usted podría considerar la optimización, pero probablemente ni siquiera entonces ...

11

Uso PropertyInfo.GetValue/FijarValor

Si tiene problemas de rendimiento en caché el objeto PropertyInfo (no llamar repetidamente GetProperty)

Si - y sólo si - el uso de la reflexión es el cuello de botella de la aplicación (como se ve en un perfilador) utiliza Delegate.CreateDelegate

Si - y realmente solo si - estás absolutamente seguro de que leer/escribir t El valor sigue siendo el peor cuello de botella, es hora de comenzar a aprender sobre el mundo divertido de generar IL en tiempo de ejecución.

Realmente dudo que valga la pena, cada uno de esos niveles aumenta la complejidad del código más que mejorar el rendimiento; hágalo solo si es necesario.

Y si el acceso en tiempo de ejecución a las propiedades es su cuello de botella de rendimiento, probablemente sea mejor ir en tiempo de compilación (es difícil tener un rendimiento genérico y súper alto al mismo tiempo).

+0

Pero posible: http: // www. codeproject.com/KB/cs/HyperPropertyDescriptor.aspx –

22

Si está buscando/configurando la misma propiedad muchas veces, usar algo para construir un método seguro será más rápido que la reflexión. Sin embargo, sugeriría usar Delegate.CreateDelegate en lugar de Reflection.Emit. Es más fácil acertar, y aún es increíblemente rápido.

Lo he usado en mi implementación de Protocol Buffers e hizo una gran diferencia frente a PropertyInfo.GetValue/SetValue. Como otros han dicho, solo haz esto después de probar que la forma más simple es demasiado lenta.

Tengo un blog post con más detalles si decides ir por la ruta CreateDelegate.

+0

Muy interesante: Intenté crear un delegado para FieldInfo.SetValue, y no cambió absolutamente nada. Bastante obvio en realidad, ya que todo lo que hice fue cambiar la forma en que se llama a la función, y es la función en sí que es lenta. Entonces, ¿cómo obtuviste este aumento de rendimiento? No tuve suerte para encontrar información al respecto en tu publicación de blog (tal vez estoy solo ciego :-D) – Steffen

+0

Solo volví a leer tu entrada de blog y vi la parte GetGetMethod y GetSetMethod, aparentemente I * were * blind antes. De todos modos, esto obviamente explica la diferencia de velocidad, sin embargo, para FieldInfos todavía estoy en la oscuridad: -S Estoy esperando el ejemplo de Marcs :-) Solo quería que supiera que descubrí lo que hizo para acelerar las cosas a través de los delegados. – Steffen

+1

Cheers (+1) - Acabo de usar esa idea para guardar .1s - .8s por página en algunas clases de reflexión poblada :-) – Keith