Frage

Es gibt viele Algorithmen Ausdrücke zu bewerten, zum Beispiel:

  1. durch rekursive Descent
  2. Rangier-Yard-Algorithmus
  3. Polish Notation umkehren

Gibt es eine Möglichkeit, jeden mathematischen Ausdruck mit C # .net Reflektion oder anderer moderner .net Technologie zu bewerten?

War es hilfreich?

Lösung

Im Anschluss an Thomas Antwort, es ist tatsächlich möglich, die (veraltet) JScript Bibliotheken direkt von C # zuzugreifen, was bedeutet, dass Sie das Äquivalent von JScript der eval Funktion verwenden können.

using Microsoft.JScript;        // needs a reference to Microsoft.JScript.dll
using Microsoft.JScript.Vsa;    // needs a reference to Microsoft.Vsa.dll

// ...

string expr = "7 + (5 * 4)";
Console.WriteLine(JScriptEval(expr));    // displays 27

// ...

public static double JScriptEval(string expr)
{
    // error checking etc removed for brevity
    return double.Parse(Eval.JScriptEvaluate(expr, _engine).ToString());
}

private static readonly VsaEngine _engine = VsaEngine.CreateEngine();

Andere Tipps

Es ist sicherlich möglich. Die CodeSnippetCompileUnit Klasse tut im Grunde diese. Ich schrieb Ihnen einige Beispiel Verwendungscode. Sie werden diese Namensräume enthalten müssen:

  • System.CodeDom.Compiler;
  • System.CodeDom;
  • Microsoft.CSharp;
  • System.Reflection;

Hier ist der Code:

string source = @"
class MyType
{
    public static int Evaluate(<!parameters!>)
    {
        return <!expression!>;
    }
}
";

string parameters = "int a, int b, int c";
string expression = "a + b * c";

string finalSource = source.Replace("<!parameters!>", parameters).Replace("<!expression!>", expression);

CodeSnippetCompileUnit compileUnit = new CodeSnippetCompileUnit(finalSource);
CodeDomProvider provider = new CSharpCodeProvider();

CompilerParameters parameters = new CompilerParameters();

CompilerResults results = provider.CompileAssemblyFromDom(parameters, compileUnit);

Type type = results.CompiledAssembly.GetType("MyType");
MethodInfo method = type.GetMethod("Evaluate");

// The first parameter is the instance to invoke the method on. Because our Evaluate method is static, we pass null.
int result = (int)method.Invoke(null, new object[] { 4, -3, 2 });

Ersetzen Sie ‚Parameter‘ und ‚Ausdruck‘ von was auch immer, und Sie haben selbst eine allgemeine Ausdrucksauswertung bekommen.

Wenn Sie eine FileNotFoundException in results.CompiledAssembly bekommen, dann scheiterte das Snippet zu kompilieren.

Sie können auch einen Blick auf die System.CodeDom.CodeSnippetExpression Klasse nehmen wollen. Es ist für speziell das Lesen Ausdrücke verwendet, sondern ein Ausdruck von selbst nicht kompiliert werden kann, so dass Sie müssten mehr CodeDom verwenden, um eine Arbeiterklasse und Verfahren um ihn herum aufzubauen. Dies ist nützlich, wenn Sie programmatisch in der Lage sein wollen, zu manipulieren, welche Art von Klasse Sie erzeugen. CodeSnippetCompileUnit ist schön, eine ganze Arbeiterklasse auf einmal (und einfacher für ein Beispiel) zu erzeugen, sondern um sie zu manipulieren Sie würden unbequem Stringmanipulationen zu tun haben.

Obwohl Compiler-Dienste eine einfache und effiziente Lösung ist, es wirft ernsthafte Sicherheitsprobleme, wenn der Ausdruck von einem Benutzer eingegeben wird, weil es so gut wie alles ausführen kann.

Es gibt eine weitere sehr einfache Lösung, die viel sicherer ist: Nutzen Sie die JScript Eval Funktion. Sie müssen nur die folgenden Schritte ausführen:

Erstellen Sie eine Datei mit dem Namen js JsMath.js:

class JsMath
{
    static function Eval(expression : String) : double
    {
        return eval(expression);
    };
}

Übersetzen in eine Klassenbibliothek:

jsc /t:library JsMath.js

Verweisen Sie auf die jsmath Bibliothek in Ihrem C # -Projekt, und verwenden Sie es wie folgt aus:

double result = JsMath.Eval(expression);

Für mich Vici.Parser sehr gut funktioniert: es hier zu überprüfen heraus, es ist die flexibelste Ausdrucksparser ich bisher gefunden habe.

(wir haben es verwendet einzurichten ‚menschenlesbare‘ Geschäftsregeln, mit Daten, die von einer SQL-Server-Datenbank zur Verfügung gestellt)

Beispiele stehen zur Verfügung und es gibt eine sehr gute Unterstützung durch den Entwickler (Überprüfung des Forum Website).

Ich denke, dies ist der beste Weg, das ist alles. Petar Repac Antwort erstaunlich. Mit Hilfe der ‚Ausdruck‘ Argument des Datacolumn Objekt löst unglaublich und einfach das Thema:

static double Evaluate(string expression)
{
    var loDataTable = new DataTable();
    var loDataColumn = new DataColumn("Eval", typeof(double), expression);
    loDataTable.Columns.Add(loDataColumn);
    loDataTable.Rows.Add(0);
    return (double)(loDataTable.Rows[0]["Eval"]);
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top