Comment puis-je évaluer une expression C# de façon dynamique?

je voudrais faire l'équivalent de:

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

suivant Biris lien, 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;

}  
44
demandé sur Daren Thomas 2008-09-10 16:06:59

7 réponses

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

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

33
répondu Biri 2018-02-21 18:56:03

j'ai écrit un projet open source, Dynamique Expresso, qui permet de convertir l'expression de texte écrite à l'aide de la syntaxe C# en délégués (ou arbre d'expression). Les expressions textuelles sont analysées et transformées en Arbres D'Expression sans utiliser de 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 L'article de Scott Gu http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .

22
répondu Davide Icardi 2013-02-07 21:46:30

ancien sujet, mais considérant que c'est l'un des premiers fils apparaissant lors de googling, voici une solution mise à jour.

Vous pouvez utiliser la nouvelle API de script de Roslyn pour évaluer les expressions.

si vous utilisez NuGet, ajoutez simplement une dépendance à Microsoft.CodeAnalysis.CSharp.Script. Pour évaluer les exemples que vous avez fourni, c'est aussi simple que:

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

cela ne fait évidemment pas usage de l'async du moteur de script capacité.

vous pouvez également spécifier le type de résultat évalué comme vous l'aviez prévu:

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

pour évaluer des extraits de code plus avancés, passer des paramètres, fournir des références, des espaces de noms et autres, Vérifier le wiki lié ci-dessus.

17
répondu Ridkuma 2017-04-26 09:51:15
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;
        }
    }
}
2
répondu Rudolf_Abel 2010-10-29 08:27:45

alors que C# n'a pas de support pour une méthode Eval nativement, j'ai un programme C# eval qui permet d'évaluer C# code. Il permet d'évaluer le code C# à l'exécution et supporte de nombreuses déclarations C#. En fait, ce code est utilisable dans n'importe quel projet .NET, cependant, il est limité à l'utilisation de la syntaxe C#. Jetez un oeil à mon site web, http://csharp-eval.com pour plus de détails.

1
répondu xnaterm 2011-06-10 02:43:50

quelles sont les implications sur le rendement de faire cela?

nous utilisons un système basé sur quelque chose comme celui mentionné ci-dessus, où chaque script C# est compilé dans un assemblage en mémoire et exécuté dans un AppDomain séparé. Il n'y a pas encore de système de mise en cache, donc les scripts sont recompilés chaque fois qu'ils sont lancés. J'ai fait quelques tests simples et un script très simple "Hello World" compile en environ 0.7 secondes sur ma machine, y compris le chargement du script à partir du disque. 0.7 secondes est très bien pour un système de script, mais pourrait être trop lent pour répondre à l'entrée de l'utilisateur, dans ce cas un analyseur/compilateur dédié comme Flee pourrait être mieux.

using System;
public class Test
{
    static public void DoStuff( Scripting.IJob Job)
    {
        Console.WriteLine( "Heps" );
    }
}
1
répondu JJJ 2014-05-04 18:34:47

on dirait Qu'il y a aussi une façon de le faire en utilisant RegEx et XPathNavigator pour évaluer l'expression. Je n'ai pas encore eu la chance de le tester mais je l'ai en quelque sorte aimé parce qu'il n'avait pas besoin de compiler du code à l'exécution ou d'utiliser des bibliothèques qui ne pouvaient pas être disponibles.

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

je vais essayer et dire plus tard si ça a marché. J'ai aussi l'intention de l'essayer à Silverlight, mais il est trop tard et je suis presque endormi de le faire maintenant.

0
répondu 2008-11-13 03:34:49