Benutzer mit den meisten Antworten
Den Inhalt einer String Variable als Code ausführen

Frage
-
Ich bin kein erfahrener Programmierer, daher erscheint diese Frage einigen wahrscheinlich trivial.Ich habe im Windows Visual Studio mit c# ein Programm geschrieben, das Integrale von mathematischen Funktionen approximiert. Das einzige Problem ist, dass ich die Funktion per hand in den Code eingeben muss, was etwas umständlich ist. Ich würde gerne einen weg finden, dass man die mathematische Funktion in ein Textfeld eingibt, diese dann als String ausliest und im Code verwenden kann. Ich hoffe sie verstehen was ich meine und freue mich über Antworten
Antworten
-
Hallo,
so trivial ist das nicht. Du kannst natürlich einen sting analysieren und dann entsprechend Funktionen aufrufen. Dafür würde ich den string in ein char array mit sting.ToCahr() umwandel und jedes char analysieren. Das Char selbst ist ein Unicode Zeichen. Die Hexadezimalen Werte von 0x30 bei 0x39 entsprechen den Zahlen 0-9. Eine weitere Möglichkeit sind reguläre ausdrücke RegEx
Gruß Thomas
Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
Dev Apps von mir: Icon für UWP, UI Strings
Andere Dev Apps: UWP Community Toolkit Sample App- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 23. Februar 2018 14:54
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 6. März 2018 14:42
-
Hi Markus,
alternativ zu Thomas' Beitrag kannst Du auch den CodeDom-Compiler nutzen. Da wird zur Laufzeit ein Programm "gebastelt", welches dann als Zeichenkette vorliegt. Dieses wird erst zur Laufzeit compiliert und dann ausgeführt. Dazu hier mal eine Windows Forms Demo. Gib mal in der TextBox zum Test ein:Math.Cos(90)
und Du erhältst das Ergebnis in der MessageBox.
using System; using System.CodeDom.Compiler; using System.Diagnostics; using System.Reflection; using System.Text; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form22 : Form { public Form22() { InitializeComponent(); } private TextBox tb = new TextBox() { Dock = DockStyle.Top }; private Button btn = new Button() { Dock = DockStyle.Top, Text = "Ausführen" }; private PictureBox pb = new PictureBox() { Dock = DockStyle.Fill }; private void Form22_Load(object sender, EventArgs e) { this.Controls.AddRange(new Control[] { btn, tb }); this.btn.Click += Btn_Click; } private void Btn_Click(object sender, EventArgs e) { try { Evaluator eval = new Evaluator(tb.Text); double res = eval.Evaluate(); MessageBox.Show(res.ToString()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public class Evaluator { private object _compiled = null; public Evaluator(string code) { CodeDomProvider comp = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true }; cp.ReferencedAssemblies.Add("system.dll"); StringBuilder sb = new StringBuilder(); sb.AppendLine("using System;"); sb.AppendLine("namespace myScripting {"); sb.AppendLine(" public class myEvaluator {"); sb.AppendLine($" public double myFunction()"); sb.AppendLine(" {"); sb.AppendLine("return " + code + ";"); sb.AppendLine("} } }"); Debug.Print(sb.ToString()); CompilerResults cr = comp.CompileAssemblyFromSource(cp, sb.ToString()); if (cr.Errors.HasErrors) { StringBuilder err = new StringBuilder(); err.AppendLine("Error Compiling Expression: "); foreach (CompilerError er in cr.Errors) err.AppendLine(er.ErrorText); throw new Exception(err.ToString()); } Assembly a = cr.CompiledAssembly; _compiled = a.CreateInstance("myScripting.myEvaluator"); } public double Evaluate() => (double)(_compiled.GetType().GetMethod("myFunction").Invoke(_compiled, null)); } } }
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 23. Februar 2018 14:56
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 6. März 2018 14:43
Alle Antworten
-
Hallo,
so trivial ist das nicht. Du kannst natürlich einen sting analysieren und dann entsprechend Funktionen aufrufen. Dafür würde ich den string in ein char array mit sting.ToCahr() umwandel und jedes char analysieren. Das Char selbst ist ein Unicode Zeichen. Die Hexadezimalen Werte von 0x30 bei 0x39 entsprechen den Zahlen 0-9. Eine weitere Möglichkeit sind reguläre ausdrücke RegEx
Gruß Thomas
Sage nie, ich kann es nicht - sage nur, ich kann es noch nicht!
Dev Apps von mir: Icon für UWP, UI Strings
Andere Dev Apps: UWP Community Toolkit Sample App- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 23. Februar 2018 14:54
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 6. März 2018 14:42
-
Hi Markus,
alternativ zu Thomas' Beitrag kannst Du auch den CodeDom-Compiler nutzen. Da wird zur Laufzeit ein Programm "gebastelt", welches dann als Zeichenkette vorliegt. Dieses wird erst zur Laufzeit compiliert und dann ausgeführt. Dazu hier mal eine Windows Forms Demo. Gib mal in der TextBox zum Test ein:Math.Cos(90)
und Du erhältst das Ergebnis in der MessageBox.
using System; using System.CodeDom.Compiler; using System.Diagnostics; using System.Reflection; using System.Text; using System.Windows.Forms; namespace WindowsFormsApp1 { public partial class Form22 : Form { public Form22() { InitializeComponent(); } private TextBox tb = new TextBox() { Dock = DockStyle.Top }; private Button btn = new Button() { Dock = DockStyle.Top, Text = "Ausführen" }; private PictureBox pb = new PictureBox() { Dock = DockStyle.Fill }; private void Form22_Load(object sender, EventArgs e) { this.Controls.AddRange(new Control[] { btn, tb }); this.btn.Click += Btn_Click; } private void Btn_Click(object sender, EventArgs e) { try { Evaluator eval = new Evaluator(tb.Text); double res = eval.Evaluate(); MessageBox.Show(res.ToString()); } catch (Exception ex) { MessageBox.Show(ex.ToString()); } } public class Evaluator { private object _compiled = null; public Evaluator(string code) { CodeDomProvider comp = CodeDomProvider.CreateProvider("CSharp"); CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, GenerateInMemory = true }; cp.ReferencedAssemblies.Add("system.dll"); StringBuilder sb = new StringBuilder(); sb.AppendLine("using System;"); sb.AppendLine("namespace myScripting {"); sb.AppendLine(" public class myEvaluator {"); sb.AppendLine($" public double myFunction()"); sb.AppendLine(" {"); sb.AppendLine("return " + code + ";"); sb.AppendLine("} } }"); Debug.Print(sb.ToString()); CompilerResults cr = comp.CompileAssemblyFromSource(cp, sb.ToString()); if (cr.Errors.HasErrors) { StringBuilder err = new StringBuilder(); err.AppendLine("Error Compiling Expression: "); foreach (CompilerError er in cr.Errors) err.AppendLine(er.ErrorText); throw new Exception(err.ToString()); } Assembly a = cr.CompiledAssembly; _compiled = a.CreateInstance("myScripting.myEvaluator"); } public double Evaluate() => (double)(_compiled.GetType().GetMethod("myFunction").Invoke(_compiled, null)); } } }
--
Viele Grüsse
Peter Fleischer (ehem. MVP)
Meine Homepage mit Tipps und Tricks- Als Antwort vorgeschlagen Dimitar DenkovMicrosoft contingent staff, Administrator Freitag, 23. Februar 2018 14:56
- Als Antwort markiert Dimitar DenkovMicrosoft contingent staff, Administrator Dienstag, 6. März 2018 14:43