I would like to do the equivalent of:
object result = Eval("1 + 3");
string now = Eval("System.DateTime.Now().ToString()") as string
Following Biri s link, I got this snippet (modified to remove obsolete method 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;
}
-
By using compile on the fly, like this example shows.
Or by using Flee, which is for exactly the same reason.
From Biri -
Remember that unless you do your compilation and execution in a seperate AppDomain, you may run into memory problems. Assemblies generated in this manner cannot be unloaded, but if you create the assembly in a seperate AppDomain you can unload the AppDomain and thereby unload the generated assembly.
From JJJ -
What are the performance implications of doing this?
Mike Dunlavey : That wasn't my downvote, but if you mention performance, my question in return is how often do you do it?From Terrapin -
What are the performance implications of doing this?
We use a system based on something like the above mentioned, where each C# script is compiled to an in-memory assembly and executed in a separate AppDomain. There's no caching system yet, so they scripts are recompiled every time they run. I've done some simple testing and a very simple "Hello World" script compiles in about 0.7 seconds on my machine, including loading the script from disk. 0.7 seconds is fine for a scripting system, but might be too slow for responding to user input, in that case a dedicated parser/compiler like Flee might be better.
using System; public class Test { static public void DoStuff( Scripting.IJob Job) { Console.WriteLine( "Heps" ); } }
From JJJ -
Looks like there is also a way of doing it using RegEx and XPathNavigator to evaluate the expression. I did not have the chance to test it yet but I kind of liked it because it did not require to compile code at runtime or use libraries that could not be available.
http://www.webtips.co.in/c/evaluate-function-in-c-net-as-eval-function-in-javascript.aspx
I'll try it and tell later if it worked. I also intend to try it in Silverlight, but it is too late and I'm almost asleep to do it now.
-
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; } } }
From Rudolf_Abel
0 comments:
Post a Comment