public static object evalCS(string Expresion) { //Si la expresión está vacía se devuelve un nulo y nos ahorramos la compilación if (Expresion.Trim() == "") return null; //Se obtiene una referencia a un compilador de C# ICodeCompiler compilador = (new CSharpCodeProvider().CreateCompiler()); //Asignamos parámetros de compilación CompilerParameters cp = new CompilerParameters(); //Se añaden las referencias mínimas cp.ReferencedAssemblies.Add("system.dll"); //Se indica que se debe generar un ejecutable... cp.GenerateExecutable = false; //..y compilar en memoria, no a disco cp.GenerateInMemory = true; //Ahora se genera el código de un ensamblado comodín al vuelo StringBuilder sbComodin = new StringBuilder(); sbComodin.Append("using System;\n"); sbComodin.Append("namespace dotNetMania {\n"); //Se crea la clase comodín para evaluar la expresión sbComodin.Append(" public class ClaseComodin {\n"); //y se crea el método comodín sbComodin.Append(" public object MetodoComodin() {\n"); //Esta es la expresión a evaluar sbComodin.AppendFormat("return ({0}); ", Expresion); //Se cierra el método sbComodin.Append("}\n"); //Se cierra la clase sbComodin.Append("}\n"); //y el espacio de nombres sbComodin.Append("}"); //Se compila el código al vuelo CompilerResults res = compilador.CompileAssemblyFromSource(cp, sbComodin.ToString()); //Se verifica si se han producido errores de compilación o no if (res.Errors.HasErrors) { //Se averigua qué errores ha habido StringBuilder errores = new StringBuilder(); errores.Append("La compilación ha producido los siguientes errores:\n"); foreach (CompilerError error in res.Errors) { errores.AppendFormat("{0}\n", error.ErrorText); } //y se genera un error para informar de ello throw new Exception(errores.ToString()); } // Si no ha habido errores de compilación se obtiene // una referencia a la clase comodín recién compilada object Comodin = res.CompiledAssembly.CreateInstance("dotNetMania.ClaseComodin"); // y usando la instrospección se llama al método // comodín de éste devolviendo el valor obtenido como un objeto return Comodin.GetType().GetMethod("MetodoComodin").Invoke(Comodin, null); } Fuente 1. El método EvalCS completo |