Compute result from string expression dynamically

Is there a way to calculate the result of a string expression, for example mystring = "2*a+32-Math.Sin(6)" dynamically knowing that a is the variable that I have, maybe some kind of dynamic solution or using System.Reflection

 string mystring = "2*a+32-Math.Sin(6)"`; decimal result = SomeMethod(mystring,3); // where a = 3 for example 
+4
source share
5 answers

How about javascript evaluating your expression?

 Type scriptType = Type.GetTypeFromCLSID(Guid.Parse("0E59F1D5-1FBE-11D0-8FF2-00A0D10038BC")); dynamic obj = Activator.CreateInstance(scriptType, false); obj.Language = "javascript"; var res = obj.Eval("a=3; 2*a+32-Math.sin(6)"); 
+14
source

You can use the Compute Datatable method in SomeMethod as follows:

  static decimal Somemethod(int val) { var result = (decimal)new DataTable().Compute(string.Format("2*{0}+32-{1}", val, Math.Sin(6)), ""); return result; } 

You can simply call it like this:

  result = Somemethod(3); 
+3
source

if you find this works fine, sorry to bother, all i wanted was a compiler on the fly. and this is what I get

 MessageBox.Show(Eval("5*3-Math.Sin(12) + 25*Math.Pow(3,2)").ToString()); public static object Eval(string sCSCode) { CodeDomProvider icc = CodeDomProvider.CreateProvider("C#"); CompilerParameters cp = new CompilerParameters(); cp.ReferencedAssemblies.Add("system.dll"); cp.ReferencedAssemblies.Add("system.xml.dll"); cp.ReferencedAssemblies.Add("system.data.dll"); cp.ReferencedAssemblies.Add("system.windows.forms.dll"); cp.ReferencedAssemblies.Add("system.drawing.dll"); cp.CompilerOptions = "/t:library"; cp.GenerateInMemory = true; StringBuilder sb = new StringBuilder(""); sb.Append("using System;\n"); sb.Append("using System.Xml;\n"); sb.Append("using System.Data;\n"); sb.Append("using System.Data.SqlClient;\n"); sb.Append("using System.Windows.Forms;\n"); sb.Append("using System.Drawing;\n"); sb.Append("namespace CSCodeEvaler{ \n"); sb.Append("public class CSCodeEvaler{ \n"); sb.Append("public object EvalCode(){\n"); sb.Append("return " + sCSCode + "; \n"); sb.Append("} \n"); sb.Append("} \n"); sb.Append("}\n"); CompilerResults cr = icc.CompileAssemblyFromSource(cp, sb.ToString()); if (cr.Errors.Count > 0) { MessageBox.Show("ERROR: " + cr.Errors[0].ErrorText, "Error evaluating cs code", MessageBoxButton.OK, MessageBoxImage.Error); return null; } System.Reflection.Assembly a = cr.CompiledAssembly; object o = a.CreateInstance("CSCodeEvaler.CSCodeEvaler"); Type t = o.GetType(); System.Reflection.MethodInfo mi = t.GetMethod("EvalCode"); object s = mi.Invoke(o, null); return s; } 
+2
source

Make an abstract class Using the methods you want to use to evaluate expressions. At run time, create a new class that inherits this one. I will send the code soon.

as promised, this is the code for this:

  public class BaseClass { public BaseClass(){} public virtual double Eval(double x,double y){return 0;} } public class MathExpressionParser { private BaseClass Evalulator=null; public MathExpressionParser(){} public bool Intialize(string equation) { Microsoft.CSharp.CSharpCodeProvider cp=new Microsoft.CSharp.CSharpCodeProvider(); System.CodeDom.Compiler.ICodeCompiler comp=cp.CreateCompiler(); System.CodeDom.Compiler.CompilerParameters cpar=new CompilerParameters(); cpar.GenerateInMemory=true; cpar.GenerateExecutable=false; cpar.ReferencedAssemblies.Add("system.dll"); cpar.ReferencedAssemblies.Add("EquationsParser.exe"); //Did you see this before; string sourceCode="using System;"+ "class DrivedEval:EquationsParser.BaseClass" + "{"+ "public DrivedEval(){}"+ "public override double Eval(double x,double y)"+ "{"+ "return "+ /*Looook here code insertion*/ equation +";"+ "}"+ "}"; //the previouse source code will be compiled now(run time); CompilerResults result=comp.CompileAssemblyFromSource(cpar,sourceCode); //If there are error in the code display it for the programmer who enter the equation string errors=""; foreach(CompilerError rrr in result.Errors) { if(rrr.IsWarning) continue; errors+="\n"+rrr.ErrorText; errors+="\n"+rrr.ToString(); } //You Can show error if there in the sourceCode you just compiled uncomment the following //MessageBox.Show(errors); if(result.Errors.Count==0&&result.CompiledAssembly!=null) { Type objtype=result.CompiledAssembly.GetType("DrivedEval"); try { if(objtype!=null) { Evalulator=(BaseClass)Activator.CreateInstance(objtype); } } catch(Exception ex) { MessageBox.Show(ex.Message,"Error in Creation the object"); } return true; } else return false; } public double evaluate(double x,double y) { if(Evalulator==null) return 0.0; return this.Evalulator.Eval(x,y); } } 

and you will need to run the following simple test to make sure it works:

 private void button1_Click(object sender, System.EventArgs e) { if(parser.Intialize(textBox1.Text)==false) { MessageBox.Show("Check equation"); return; } textBox4.Text=(parser.evaluate(double.Parse(textBox2.Text),double.Parse(textBox3.Text))).ToString(); } 
+1
source

I don’t think there is any support for what you are asking, however there are several ways to achieve it, none of which is trivial, but in the order in which I think they are easy:

+1
source

Source: https://habr.com/ru/post/1434292/


All Articles