可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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;
}
回答1:
By using compile on the fly, like this example shows.
Or by using Flee, which is for exactly the same reason.
回答2:
I have written an open source project, Dynamic Expresso, that can convert text expression written using a C# syntax into delegates (or expression tree). Text expressions are parsed and transformed into Expression Trees without using compilation or reflection.
You can write something like:
var interpreter = new Interpreter();
var result = interpreter.Eval(\"8 / 2 + 2\");
or
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);
My work is based on Scott Gu article http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx .
回答3:
Old topic, but considering this is one of the first threads showing up when googling, here is an updated solution.
You can use Roslyn\'s new Scripting API to evaluate expressions.
If you are using NuGet, just add a dependency to Microsoft.CodeAnalysis.CSharp.Scripting.
To evaluate the examples you provided, it is as simple as:
var result = CSharpScript.EvaluateAsync(\"1 + 3\").Result;
This obviously does not make use of the scripting engine\'s async capabilities.
You can also specify the evaluated result type as you intended:
var now = CSharpScript.EvaluateAsync<string>(\"System.DateTime.Now.ToString()\").Result;
To evaluate more advanced code snippets, pass parameters, provide references, namespaces and whatnot, check the wiki linked above.
回答4:
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;
}
}
}
回答5:
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 the 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\" );
}
}
回答6:
If you specifically want to call into code and assemblies in your own project I would advocate using the C# CodeDom CodeProvider.
Here is a list of the most popular approaches that I am aware of for evaluating string expressions dynamically in C#.
Microsoft Solutions
- C# CodeDom CodeProvider:
- See How LINQ used to work and this CodeProject article
- Roslyn:
- See this article on Rosly Emit API and this StackOverflow answer
- DataTable.Compute:
- See this answer on StackOverflow
- Webbrowser.Document.InvokeScript
- See this StackOverflow question
- DataBinder.Eval
- ScriptControl
- See this answer on StackOverflow and this question
- Executing PowerShell:
- See this CodeProject article
Non-Microsoft solutions (not that there is anything wrong with that)
- Expression evaluation libraries:
- Flee
- DynamicExpresso
- NCalc
- Roll your own a language building toolkit like:
回答7:
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.
回答8:
While C# doesn\'t have any support for an Eval method natively, I have a C# eval program that does allow for evaluating C# code. It provides for evaluating C# code at runtime and supports many C# statements. In fact, this code is usable within any .NET project, however, it is limited to using C# syntax. Have a look at my website, http://csharp-eval.com, for additional details.