Documente Academic
Documente Profesional
Documente Cultură
EJECUCIÓN AL VUELO DE CÓDIGO TECLEADO POR EL USUARIO
Nivel: Intermedio
por Alberto Población
Con cierta frecuencia se repiten en los foros de .Net preguntas como la siguiente:
¿Cómo podría hacer que mi programa permita al usuario escribir una fórmula matemática
en una cadena de texto, como por ejemplo “1+2*Sin(0.5)” y luego obtener el resultado de
la misma?
O bien ciertas variantes de la misma pregunta tales como:
Deseo introducir en un TextBox una ecuación tal como “y=5*x^2‐3*x+1” y que mi
programa dibuje la gráfica de esta función.
En todos los casos, se trata de que el programa sea capaz de interpretar y evaluar una
expresión que sólo se conoce en tiempo de ejecución. Lógicamente, si la expresión
fuera conocida en tiempo de compilación, bastaría con incorporarla al código de
nuestro programa y el compilador generaría sin ningún problema las instrucciones
correspondientes.
Del mismo modo, si deseamos hacerlo en un lenguaje interpretado que disponga ya de
una instrucción para evaluar código (como por ejemplo el método eval de JavaScript),
esta tarea no tiene la más mínima dificultad. Sin embargo, en nuestro caso
presumimos que se quiere escribir el programa en uno de los lenguajes de .Net, tales
como C# o VB.Net, que no aportan esta funcionalidad directamente.
Para ello se nos presentan varias opciones:
• Escribir un intérprete o compilador basado en un analizador sintáctico hecho
por nosotros mismos. Esta vía es la única posible cuando la sintaxis de las
expresiones que queremos admitir no coincide con la de un lenguaje de
programación ya existente y accesible desde nuestra aplicación. Aunque
parezca muy complicado, es razonablemente fácil si las expresiones son de
cierta sencillez. En un futuro artículo presentaremos esta técnica con algún
ejemplo simple.
• Compilar la expresión sobre la marcha mediante uno de los compiladores de
.Net, y a continuación ejecutar el código que hemos compilado. Esta es la
técnica que elaboraremos en las líneas que siguen.
Compilar las expresiones sobre la marcha
Para aplicar el procedimiento consistente en compilar la expresión y llamar a la función
compilada, realizaremos las siguientes operaciones:
1. Construimos un pequeño fragmento de código fuente que tenga la sintaxis
correcta para ser compilado con el compilador del lenguaje elegido. En el
ejemplo que se incluye más abajo hemos declarado una clase MiClase que
contiene una función Evaluar, y dentro de la función hemos concatenado la
cadena introducida por el usuario (expresion). Todo ello da lugar a un
string llamado fuente que contiene el código a compilar.
3. Crear una variable del tipo CompilerParameters, en la que estableceremos
los parámetros de compilación. En particular, añadiremos todas las referencias
a librerías que hayan de ser enlazadas con nuestro mini‐programa, e
indicaremos que el resultado de la compilación sólo ha de ser temporal
mediante la propiedad GenerateInMemory.
6. Sobre este Assembly utilizamos las habituales técnicas ya conocidas de
System.Reflection para invocar el método que previamente habíamos
introducido en nuestro código fuente. El resultado devuelto por el método es
precisamente el resultado de evaluar la expresión que nos interesaba.
En el caso de que la expresión haya de ser evaluada repetidamente, como por ejemplo
cuando tengamos que dibujar una gráfica de una función, todos los pasos necesarios
para la compilación basta darlos una sola vez. Una vez compilada la expresión,
podemos hacer llamadas repetidas para ir pintando la función punto por punto. Esto
es lo que hemos hecho en nuestro ejemplo, que presenta una clase llamada
Evaluador cuyo constructor recibe la expresión introducida por el usuario y realiza
todos los pasos previos para llamarla. Más abajo, contiene una función llamada
Evaluar que es la que llamaremos múltiples veces, cuando sea necesario realizar el
cálculo de la expresión compilada.
A continuación presentamos el listado con el código mencionado, en el que por
claridad se han omitido todas las comprobaciones para control de errores:
using System.CodeDom.Compiler;
using System.Reflection;
...
public class Evaluador
{
private MethodInfo mi;
private Object evaluador;
CodeDomProvider compilador =
CodeDomProvider.CreateProvider("CSharp");
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
CompilerResults cr =
compilador.CompileAssemblyFromSource(cp,
fuente);
Assembly a = cr.CompiledAssembly;
evaluador = a.CreateInstance("MiCodigo.MiClase",
false, System.Reflection.BindingFlags.CreateInstance, null,
new object[0], null, null);
Type t = evaluador.GetType();
mi = t.GetMethod("Evaluar");
}
Ten en cuenta que cada vez que compilas con esta técnica se genera un ensamblado
que queda cargado en memoria. El ejemplo anterior está destinado a dibujar la gráfica
de una curva, por lo que la idea la función se compila una sola vez y luego se evalúa
miles de veces. Por supuesto, si se compilase cada una de las veces, sería un gran
problema porque irían quedando multitud de ensamblados en memoria, ocupando
cada vez más y siendo totalmente desaconsejable.
El remedio para esto es cargarlos todos dentro de un AppDomain reservado a tal
efecto. Posteriormente, cuando ya no nos hicieran falta las funciones, se puede
descargar de memoria el dominio e aplicación usando su método Unload. Quizá en un
próximo artículo expliquemos con detalle la técnica del AppDomain, pero por ahora
debes quedarte con las ideas explicadas en este documento y trabajarlas con cuidado,
pes pueden ser muy útiles.
Acerca del autor
Alberto Población lleva 27 años desarrollando software. Ha sido reconocido por Microsoft
como MVP (Most Valuable Professional) de C#. Cuenta, entre otras, con las certificaciones MCT,
MCSE, MCDBA, MCITP, MCSD y MCPD en sus tres variantes (Desarrollador Web, Desarrollador
Windows y Desarrollador de Aplicaciones Empresariales). En la actualidad se dedica
principalmente a la formación, asesoramiento y desarrollo de aplicaciones. Es tutor de
campusMVP.
Acerca de campusMVP
CampusMVP te ofrece la mejor formación en tecnología Microsoft a través de nuestros cursos
online y nuestros libros especializados, impartidos y escritos por conocidos MVP de Microsoft.
Visita nuestra página y prueba nuestros cursos y libros gratuitamente. www‐campusmvp.com
Reconocimiento ‐ NoComercial ‐ CompartirIgual (by‐nc‐sa):
No se permite un uso comercial de este documento ni de las posibles obras derivadas, la
distribución de las cuales se debe hacer con una licencia igual a la que regula esta obra
original. Se debe citar la fuente.