61 votes

Comment puis-je évaluer une expression C # de manière dynamique?

Je voudrais faire l'équivalent de:

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

Après le lien de Biri, j’ai eu cet extrait (modifié pour supprimer la méthode obsolète 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;

}
 

31voto

Davide Icardi Points 2215

J'ai écrit un projet open source, Dynamique Expresso, que peut convertir le texte en expression écrite à l'aide d'une syntaxe C# dans délégués (ou de l'expression de l'arbre). Expressions de texte sont analysées et transformées en Arbres d'Expression sans l'aide de la compilation ou de réflexion.

Vous pouvez écrire quelque chose comme:

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

ou

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);

Mon travail est basé sur Scott Gu article http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

29voto

Biri Points 4992

En utilisant la compilation à la volée, comme le montre cet exemple .

Ou en utilisant Flee , qui est pour la même raison.

5voto

JJJ Points 149

N'oubliez pas que, sauf si vous effectuez la compilation et l'exécution dans un AppDomain séparé, vous risquez de rencontrer des problèmes de mémoire. Les assemblys générés de cette manière ne peuvent pas être déchargés, mais si vous créez l'assembly dans un AppDomain séparé, vous pouvez décharger l'AppDomain et par conséquent décharger l'assembly généré.

3voto

Jonathan Wood Points 26443

Voici une solution utilisant rien de plus que du code C #.

http://www.blackbeltcoder.com/Articles/algorithms/ac-expression-evaluator

2voto

Rudolf_Abel Points 21
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;
        }
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X