Wie kann ich einen C#-Ausdruck dynamisch auswerten?
-
09-06-2019 - |
Frage
Ich würde gerne das Äquivalent von Folgendem tun:
object result = Eval("1 + 3");
string now = Eval("System.DateTime.Now().ToString()") as string
Im Anschluss an Biri s Verknüpfung, ich habe dieses Snippet erhalten (geändert, um veraltete Methode zu entfernen 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;
}
Lösung
Mit der on the fly mit kompilieren, wie diesem Beispiel zeigt.
Andere Tipps
Ich habe ein Open-Source-Projekt geschrieben, Dynamische Expresso , dass Textausdruck umwandeln kann mit einem schriftlichen C # Syntax in Teilnehmer (oder Ausdrucksbaum). Text Ausdrücke werden analysiert und umgewandelt in Expression Trees ohne Kompilierung oder Reflexion verwendet wird.
Sie können so etwas wie schreiben:
var interpreter = new Interpreter();
var result = interpreter.Eval("8 / 2 + 2");
oder
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);
Meine Arbeit basiert auf Scott Gu Artikel http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic- abfrage library.aspx .
Altes Thema, aber dies unter Berücksichtigung einer der ersten Fäden zeigen, wenn googeln, hier ist eine aktualisierte Lösung.
Sie können mit Roslyn der neuen Scripting-API-Ausdrücke auszuwerten .
Wenn Sie NuGet verwenden, fügen Sie nur eine Abhängigkeit Microsoft.CodeAnalysis. CSharp.Scripting . Zur Auswertung der Beispiele, die Sie zur Verfügung gestellt, ist es so einfach wie:
var result = CSharpScript.EvaluateAsync("1 + 3").Result;
Dies ist offensichtlich nicht Nutzung des Scripting-Engine Asynchron-Fähigkeiten machen.
Sie können auch die ausgewertete Ergebnis Typ angeben, wie Sie bestimmt:
var now = CSharpScript.EvaluateAsync<string>("System.DateTime.Now.ToString()").Result;
Um erweiterte Code-Schnipsel zu bewerten, Parameter übergeben, liefern Hinweise, Namensräume und so weiter, überprüfen Sie die Wiki oben verknüpft.
Wenn Sie speziell nennen in Code und Baugruppen in Ihrem eigenen Projekt möchte ich befürworten die C # CodeDom CodeProvider .
Hierist eine Liste der beliebtesten Ansätze, die ich bin mir bewusst, für die Auswertung String-Ausdrücke dynamisch in C #.
Microsoft Solutions
- C # CodeDom CodeProvider :
- Siehe Wie LINQ verwendet zu arbeiten und diese Codeproject Artikel
- Roslyn :
- Sehen Sie diesen Artikel auf Rosly rel="nofollow Emit-API und diese Stackoverflow beantworten
- DataTable.Compute :
- Sehen Sie diese Antwort auf Stackoverflow
- Webbrowser.Document.InvokeScript
- Sehen Sie diese Frage Stackoverflow
- DataBinder.Eval
- Script
- Siehe diese Antwort auf Stackoverflow und < a href = "https://stackoverflow.com/questions/16075775/calling-the-javascript-functions-inside-c-sharp-for-a-64-bit-project?noredirect=1&lq=1"> diese Frage
- Ausführen von Powershell:
Non-Microsoft-Lösungen (nicht, dass es etwas falsch mit, dass)
- Expression Evaluation Bibliotheken:
- Rollen Sie Ihre eigene Sprache Gebäude Toolkit wie:
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;
}
}
}
Was sind die Auswirkungen auf die Leistung, dies zu tun?
Wir verwenden ein System, das auf so etwas wie die oben genannten, wobei jeder C # Skript zu einer In-Memory-Anordnung zusammengestellt und in einer separaten AppDomain ausgeführt. Es gibt keine Caching-System noch, so werden die Skripte jedesmal, wenn sie neu kompiliert laufen. Ich habe ein paar einfachen Tests und ein sehr einfaches „Hallo Welt“ Skript erstellt auf meinem Rechner in etwa 0,7 Sekunden erledigt, darunter das Skript von der Festplatte geladen werden. 0,7 Sekunden sind in Ordnung für ein Scripting-System, aber möglicherweise zu langsam für auf Benutzereingaben reagiert, in diesem Fall einen eigenen Parser / Compiler wie besser sein Fliehen könnte.
using System;
public class Test
{
static public void DoStuff( Scripting.IJob Job)
{
Console.WriteLine( "Heps" );
}
}
Sieht aus wie es ist auch ein Weg, es zu tun mit RegEx und XPathNavigator den Ausdruck auszuwerten. Ich habe nicht die Chance haben, es noch zu testen, aber ich irgendwie mochte es, weil es keinen Code zur Laufzeit oder Verwendung Bibliotheken kompilieren bedurften, die nicht verfügbar sein könnte.
http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx
Ich werde es versuchen und später sagen, ob es funktioniert. Ich beabsichtige, es auch in Silverlight zu versuchen, aber es ist zu spät und ich bin fast schlafend, es jetzt zu tun.
Während C # hat keine Unterstützung für eine Eval-Methode nativ, ich habe ein C # eval-Programm, das für die Bewertung C # -Code nicht gestattet. Es bietet für C # -Code zur Laufzeit zu bewerten und viele C # Anweisungen unterstützt. In der Tat ist dieser Code verwendbar innerhalb eines beliebigen .NET-Projektes, ist es jedoch zur Verwendung von C # Syntax begrenzt ist. Werfen Sie einen Blick auf meine Website, http://csharp-eval.com , für weitere Details.