c# .net reflection reflection.emit

c# - Usos del mundo real de Reflection.Emit



.net (16)

En todos los libros que he leído después de reflexionar, a menudo dicen que no hay muchos casos en los que desee generar IL sobre la marcha, pero no dan ningún ejemplo de dónde tiene sentido.

Después de ver Reflection.Emit como requisito de trabajo para una empresa de juegos, sentí curiosidad sobre dónde más se usa.

Ahora me pregunto si hay situaciones que hayas visto en el mundo real si fuera la mejor solución al problema. Tal vez se utiliza como una implementación de un patrón de diseño?

Tenga en cuenta que imagino que PostSharp / AOP lo usa.


  1. Genere código declarativo, como el uso de la interfaz para declarar el servicio HTTP REST subyacente. https://github.com/neurospeech/retro-core-fit

  2. Aumentador de rendimiento, la mayoría de las veces utilizo Expression.Compile para crear un fragmento de código para recuperar información rápidamente compilando la expresión de un delegado compilado que se puede ejecutar en el futuro. Si usa PropertyInfo.GetValue , es muy lento, pero si crea una expresión para acceder a la propiedad y compilarla a un delegado (que internamente utiliza Reflection.Emit), se logra un gran ahorro en tiempo de CPU.



Generando enums a partir de datos externos:

Enum dinámico en C #

En ese ejemplo, los datos provienen de una base de datos de búsqueda y la enumeración se crea en tiempo de compilación leyendo fuera de la base de datos. Esto mantiene la seguridad de tipo sin tener que mantener manualmente fuentes de información duplicadas.



Las bibliotecas de burla también usan Reflection.Emit para generar proxies usados ​​en Unit Testing.


Lo estoy usando como una forma de crear proxies dinámicos sobre la marcha para envolver una clase. NHibernate utiliza este mismo patrón para las llamadas de proxy a los objetos de POCO en lugar de consultar una base de datos.

Cada vez que desee poder "escribir código" (es decir, crear una nueva función, etc.) dinámicamente, necesitará Emit .


Lo he usado en una aplicación donde se tuvo que acceder a una propiedad repetidamente a través de la reflexión (porque el nombre de la propiedad no se conocía en tiempo de compilación).

Al crear una clase auxiliar en tiempo de ejecución que genera código para acceder a la propiedad, el código resultante fue un orden de magnitud más rápido que el código original de solo reflexión.


Los lenguajes relacionados con DLR y DLR dependen en gran medida de Reflection.Emit


Me gusta explorar más para el AI-Inspired para el autoaprendizaje. Nos permite crear una clase o módulo en tiempo de ejecución


Por ejemplo, Entity Framework utiliza Reflection.Emit para crear clases de proxy en tiempo de ejecución que heredan de sus clases de modelo para proporcionar carga diferida y seguimiento de cambios .


Recientemente lo utilicé para crear una prueba de concepto para compilar un conjunto de operaciones que es muy costoso de hacer en tiempo de ejecución, y obtuve una mejora del 200% en la velocidad. Las operaciones debían usar RegEx para analizar una cadena grande y recorrer las coincidencias, usar Reflection para buscar y crear instancias de tipos, y un montón de otras cosas que no son exactamente rápidas. Al usar IL emit, creé funciones dinámicas que coincidían con un tipo de delegado (usando DynamicMethod) y las almacenaba en caché. Hice la danza RegEx / Reflection normal una vez por valor de entrada para descubrir qué debería hacer, luego usé StringBuilder para concatenar las cadenas como literales, y en lugar de Reflection / Activator ahora podía usar los tipos reales en la IL emitida. Aquí hay un consejo útil: no intente escribir IL usted mismo a menos que sea un sado-masoquista. Escriba una función de muestra o escriba C # que haga lo que quiera, compílelo y use Reflector o ILDASM para ver el IL generado. Luego usa Emit para hacer una lógica similar. Otro consejo es que puede crear locales y almacenarlos en variables, luego usar Emit (OpCodes.Ldloc, myLocalVar) y obtendrá la dirección local para usted, en lugar de tener que hacer un seguimiento del índice local (es decir, ldloc_1).


Recuerdo haber visto Relection.Emit utilizado en el capítulo 8: "Generación de código on-the-fly para procesamiento de imágenes" de Beautiful Code . Básicamente, el autor se especializa en una función para realizar un determinado conjunto de operaciones de procesamiento de imágenes en una imagen determinada, lo que a su vez conduce a un tiempo de ejecución muy reducido.



Castle DynamicProxy lo usa para, supongo, proxies dinámicos. DynamicProxy es luego utilizado por el contenedor IoC del Castle Windsor y el asignador OR ActiveRecord.



Expression.Compile esencialmente hace esto: esa es la clave de algunos de LINQ.

Actualmente estoy usando la emisión de reflejos para volver a escribir una API de serialización, porque a veces la reflexión no es lo suficientemente buena. Da la casualidad que esto también le permitirá generar dlls (al igual que funciona sgen), lo que permite un código totalmente estático (espero que esto lo haga compatible con el iPhone).

También uso un enfoque similar en HyperDescriptor para proporcionar una búsqueda de propiedades basada en el nombre muy rápida.

También utilicé emit para hacer cosas como:

todo relacionado con las preguntas SO.

Finalmente, este enfoque IL es el núcleo de protobuf-net "v2"; la razón aquí es que me permite tener un modelo rápido en tiempo de ejecución (compilarlo vía IL sobre la marcha) y escribirlo directamente en un dll compilado estáticamente, para que funcione en cosas como iPhone, Phone 7 , etc. (que no tienen las API de meta-programación necesarias).