Pregunta

Me gustaría hacer el equivalente a:

object result = Eval("1 + 3");
string now    = Eval("System.DateTime.Now().ToString()") as string

Siguiendo a Biri enlace, obtuve este fragmento (modificado para eliminar el método obsoleto ICodeCompiler.CreateCompiler():

private object Eval(string sExpression)
{
    CSharpCodeProvider c = new CSharpCodeProvider();
    CompilerParameters cp = new CompilerParameters();

    cp.ReferencedAssemblies.Add("system.dll");

    cp.CompilerOptions = "/t:library";
    cp.GenerateInMemory = true;

    StringBuilder sb = new StringBuilder("");
    sb.Append("using System;\n");

    sb.Append("namespace CSCodeEvaler{ \n");
    sb.Append("public class CSCodeEvaler{ \n");
    sb.Append("public object EvalCode(){\n");
    sb.Append("return " + sExpression + "; \n");
    sb.Append("} \n");
    sb.Append("} \n");
    sb.Append("}\n");

    CompilerResults cr = c.CompileAssemblyFromSource(cp, sb.ToString());
    if (cr.Errors.Count > 0)
    {
        throw new InvalidExpressionException(
            string.Format("Error ({0}) evaluating: {1}", 
            cr.Errors[0].ErrorText, sExpression));
    }

    System.Reflection.Assembly a = cr.CompiledAssembly;
    object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler");

    Type t = o.GetType();
    MethodInfo mi = t.GetMethod("EvalCode");

    object s = mi.Invoke(o, null);
    return s;

}  
¿Fue útil?

Solución

Usando compilar sobre la marcha, como este ejemplo muestra.

O usando Huir, que es exactamente por la misma razón.

Otros consejos

He escrito un proyecto de código abierto, expreso dinámico, que puede convertir expresiones de texto escritas con una sintaxis de C# en delegados (o árbol de expresiones).Las expresiones de texto se analizan y transforman en Árboles de expresión sin utilizar compilación o reflexión.

Puedes escribir algo como:

var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");

o

var interpreter = new Interpreter()
                .SetVariable("service", new ServiceExample());

string expression = "x > 4 ? service.aMethod() : service.AnotherMethod()";

Lambda parsedExpression = interpreter.Parse(expression, 
                        new Parameter("x", typeof(int)));

parsedExpression.Invoke(5);

Mi trabajo se basa en el artículo de Scott Gu. http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

Tema antiguo, pero considerando que este es uno de los primeros hilos que aparecen al buscar en Google, aquí hay una solución actualizada.

Puedes usar La nueva API de scripting de Roslyn para evaluar expresiones.

Si está utilizando NuGet, simplemente agregue una dependencia a Microsoft.CodeAnalysis.CSharp.Scripting.Para evaluar los ejemplos que proporcionó, es tan simple como:

var result = CSharpScript.EvaluateAsync("1 + 3").Result;

Obviamente, esto no hace uso de las capacidades asíncronas del motor de secuencias de comandos.

También puede especificar el tipo de resultado evaluado según lo previsto:

var now = CSharpScript.EvaluateAsync<string>("System.DateTime.Now.ToString()").Result;

Para evaluar fragmentos de código más avanzados, pasar parámetros, proporcionar referencias, espacios de nombres y demás, consulte la wiki vinculada anteriormente.

Si desea específicamente invocar código y ensamblajes en su propio proyecto, recomendaría usar el Proveedor de código C# CodeDom.

Aquí hay una lista de los enfoques más populares que conozco para evaluar expresiones de cadena dinámicamente en C#.

Soluciones Microsoft

Soluciones que no son de Microsoft (no es que haya nada malo en ello)

using System;
using Microsoft.JScript;
using Microsoft.JScript.Vsa;
using Convert = Microsoft.JScript.Convert;

namespace System
{
    public class MathEvaluator : INeedEngine
    {
        private VsaEngine vsaEngine;

        public virtual String Evaluate(string expr)
        {
            var engine = (INeedEngine)this;
            var result = Eval.JScriptEvaluate(expr, engine.GetEngine());

            return Convert.ToString(result, true);
        }

        VsaEngine INeedEngine.GetEngine()
        {
            vsaEngine = vsaEngine ?? VsaEngine.CreateEngineWithType(this.GetType().TypeHandle);
            return vsaEngine;
        }

        void INeedEngine.SetEngine(VsaEngine engine)
        {
            vsaEngine = engine;
        }
    }
}

¿Cuáles son las implicaciones de rendimiento de hacer esto?

Usamos un sistema basado en algo como lo mencionado anteriormente, donde cada script C# se compila en un ensamblado en memoria y se ejecuta en un AppDomain separado.Aún no existe un sistema de almacenamiento en caché, por lo que los scripts se recompilan cada vez que se ejecutan.Hice algunas pruebas simples y un script muy simple "Hello World" se compila en aproximadamente 0,7 segundos en mi máquina, incluida la carga del script desde el disco.0,7 segundos está bien para un sistema de secuencias de comandos, pero puede ser demasiado lento para responder a la entrada del usuario; en ese caso, un analizador/compilador dedicado como Flee podría ser mejor.

using System;
public class Test
{
    static public void DoStuff( Scripting.IJob Job)
    {
        Console.WriteLine( "Heps" );
    }
}

Parece que también hay una manera de hacerlo usando RegEx y XPathNavigator para evaluar la expresión.No tuve la oportunidad de probarlo todavía, pero me gustó porque no requería compilar código en tiempo de ejecución ni usar bibliotecas que no podían estar disponibles.

http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx

Lo probaré y luego te diré si funcionó.También tengo intención de probarlo en Silverlight, pero ya es demasiado tarde y ya casi estoy dormido para hacerlo.

Si bien C# no admite ningún método de evaluación de forma nativa, tengo un programa de evaluación de C# que permite evaluar el código de C#.Proporciona la evaluación del código C# en tiempo de ejecución y admite muchas declaraciones de C#.De hecho, este código se puede utilizar en cualquier proyecto .NET; sin embargo, está limitado al uso de la sintaxis de C#.Echa un vistazo a mi sitio web, http://csharp-eval.com, para obtener detalles adicionales.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top