Reflexión.Emitir vs CodeDom


¿Cuáles son algunos pros/contras para el uso de la Reflexión.Emit library versus 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 formato XML. Generaré clases que amplíen las clases existentes en el ensamblaje de la aplicación, implementaré interfaces adicionales, agregaré métodos y anularé miembros virtuales y abstractos.

Quiero hacer seguro que selecciono la técnica apropiada antes de entrar demasiado 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 simplifiquen o agilicen el trabajo de wither cualquiera de las API también sería útil.

Author: LBushkin, 2010-03-03

3 answers

Creo que los puntos clave sobre el código y la Reflexión.Emit son los siguientes:

  • CodeDom genera código fuente en 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 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 el código fuente de C# y luego ejecuta el compilador para analizarlo (¡otra vez!) y compilarlo. Puede generar código utilizando construcciones de nivel relativamente alto (similares a expresiones y sentencias de C#) como bucles.

  • Reflexión.Emit genera un IL por lo que produce directamente un ensamblado que también puede almacenarse solo en memoria. Como resultado, es mucho más eficiente.Tienes que generar código IL de bajo nivel (los valores se almacenan en la pila; el bucle tiene que implementarse usando saltos), por lo que generar una lógica más complicada es un poco complicado.

En general, creo que la Reflexión.Emit se considera generalmente 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 funcionarían 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 de.NET).

Otra opción sería utilizar el Expression clase . En. NET 4.0 it permite generar código equivalente a expresiones y sentencias de C#. Sin embargo, no le permite generar clases. Por lo tanto, usted puede ser capaz de combinar esto con la Reflexión.Emit (para generar clases que deleguen la implementación al código generado usando Expression). Para algunos escenarios también puede que no 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).

 54
Author: Tomas Petricek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-12 12:58:30

El código que se dirige a 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 tu código CodeDom mal, obtienes un error del compilador; si generas IL inválido, obtienes una excepción fatal o un crash.

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

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

 14
Author: Tim Robinson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-02 22:56:42

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

 6
Author: Vlad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-03-02 21:35:08