what tutorial how create c# .net code-generation reflection.emit codedom

c# - tutorial - Reflection.Emit vs CodeDOM



system reflection c# (3)

¿Cuáles son algunas de las ventajas y desventajas de usar la biblioteca Reflection.Emit frente a CodeDOM para generar código dinámicamente en tiempo de ejecución?

Estoy tratando de generar algunas clases dinámicas (relativamente complicadas) en un sistema basado en metadatos disponibles en tiempo de ejecución en forma XML. Generaré clases que extiendan las clases existentes en el ensamblaje de la aplicación, implementando interfaces adicionales, agregando métodos y anulando miembros virtuales y abstractos.

Quiero asegurarme de seleccionar la técnica adecuada antes de profundizar en la implementación. Cualquier información sobre cómo difieren estas diferentes técnicas de generación de código sería útil. Además, cualquier información sobre bibliotecas de código abierto que simplifique o simplifique el trabajo con cualquiera de las API también sería útil.


Código que apunta CodeDom tiende a ser más fácil de mantener, ya que está generando código C # y no IL (más personas pueden leer C # que IL). Además, si obtienes un código CodeDom incorrecto, obtienes un error de compilación; Si genera IL no válida, obtiene una excepción fatal o un bloqueo.

Sin embargo, debido a que CodeDom invoca el compilador csc.exe , es un poco más lento preparar el código para su uso. Con Reflection.Emit, puede generar código directamente en la memoria.

CodeDom probablemente está bien para la mayoría de las cosas; el XmlSerializer y el diseñador de WinForms lo utilizan.


Creo que los puntos clave sobre CodeDOM y Reflection.Emit son los siguientes:

  • CodeDom genera código fuente de C # y generalmente se usa cuando se genera código para ser incluido como parte de una solución y compilado en el IDE (por ejemplo, las clases de LINQ to SQL, WSDL, XSD funcionan de esta manera). En este escenario, también puede usar clases parciales para personalizar el código generado. Es menos eficiente, porque genera la fuente C # y luego ejecuta el compilador para analizarlo (¡otra vez!) Y compilarlo. Puede generar código utilizando construcciones de nivel relativamente alto (similares a las expresiones y declaraciones de C #) como los bucles.

  • Reflection.Emit genera un IL por lo que produce directamente un ensamblaje que también puede almacenarse en la memoria. Como resultado, es mucho más eficiente. Debe generar un código IL de bajo nivel (los valores se almacenan en la pila; los bucles deben implementarse mediante saltos), por lo que generar una lógica más complicada es un poco difícil.

En general, creo que Reflection.Emit generalmente se considera como la forma preferida de generar código en tiempo de ejecución, mientras que CodeDOM se prefiere cuando se genera código antes del tiempo de compilación. En su escenario, ambos probablemente funcionen bien (aunque CodeDOM puede necesitar privilegios más altos, porque en realidad necesita invocar el compilador de C #, que es parte de cualquier instalación .NET).

Otra opción sería usar la clase de Expression . En .NET 4.0, le permite generar código equivalente a expresiones y declaraciones en C #. Sin embargo, no te permite generar clases. Por lo tanto, es posible que pueda combinar esto con Reflection.Emit (para generar clases que delegan la implementación al código generado con Expression ). Para algunos escenarios, es posible que tampoco necesite una jerarquía de clases completa; a menudo, un diccionario de delegados generados dinámicamente como Dictionary<string, Action> podría ser lo suficientemente bueno (pero, por supuesto, depende de su escenario exacto).


Es posible que desee ver ExpandoObject . Sin embargo, es .NET 4.0 solamente.