如何动态评估 C# 代码?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4629/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How can I evaluate C# code dynamically?
提问by Adhip Gupta
I can do an eval("something()");
to execute the code dynamically in JavaScript. Is there a way for me to do the same thing in C#?
我可以eval("something()");
在 JavaScript 中动态执行代码。有没有办法让我在 C# 中做同样的事情?
An example of what I am trying to do is: I have an integer variable (say i
) and I have multiple properties by the names: "Property1", "Property2", "Property3", etc.
Now, I want to perform some operations on the " Propertyi" property depending on the value of i
.
我想要做的一个例子是:我有一个整数变量(比如i
),我有多个属性的名称:“Property1”、“Property2”、“Property3”等。现在,我想执行一些操作在“属性i”属性上取决于 的值i
。
This is really simple with Javascript. Is there any way to do this with C#?
这对于 Javascript 来说非常简单。有没有办法用 C# 做到这一点?
采纳答案by Lasse V. Karlsen
Unfortunately, C# isn't a dynamic language like that.
不幸的是,C# 不是那样的动态语言。
What you can do, however, is to create a C# source code file, full with class and everything, and run it through the CodeDom provider for C# and compile it into an assembly, and then execute it.
但是,您可以做的是创建一个包含类和所有内容的 C# 源代码文件,然后通过 C# 的 CodeDom 提供程序运行它并将其编译为程序集,然后执行它。
This forum post on MSDN contains an answer with some example code down the page somewhat:
create a anonymous method from a string?
MSDN 上的这个论坛帖子在页面下方包含一些示例代码的答案:
从字符串创建匿名方法?
I would hardly say this is a very good solution, but it is possible anyway.
我很难说这是一个非常好的解决方案,但无论如何它都是可能的。
What kind of code are you going to expect in that string? If it is a minor subset of valid code, for instance just math expressions, it might be that other alternatives exists.
您希望在该字符串中使用什么样的代码?如果它是有效代码的次要子集,例如只是数学表达式,则可能存在其他替代方案。
Edit: Well, that teaches me to read the questions thoroughly first. Yes, reflection would be able to give you some help here.
编辑:嗯,这教我首先彻底阅读问题。是的,反思可以在这里给你一些帮助。
If you split the string by the ; first, to get individual properties, you can use the following code to get a PropertyInfo object for a particular property for a class, and then use that object to manipulate a particular object.
如果你用 ; 分割字符串 首先,要获取单个属性,您可以使用以下代码为类的特定属性获取 PropertyInfo 对象,然后使用该对象来操作特定对象。
String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);
回答by David Wengier
You can use reflection to get the property and invoke it. Something like this:
您可以使用反射来获取属性并调用它。像这样的东西:
object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);
That is, assuming the object that has the property is called "theObject" :)
也就是说,假设具有该属性的对象称为“theObject”:)
回答by GateKiller
You could do it with a prototype function:
您可以使用原型函数来做到这一点:
void something(int i, string P1) {
something(i, P1, String.Empty);
}
void something(int i, string P1, string P2) {
something(i, P1, P2, String.Empty);
}
void something(int i, string P1, string P2, string P3) {
something(i, P1, P2, P3, String.Empty);
}
and so on...
等等...
回答by Karl Seguin
Not really. You can use reflection to achieve what you want, but it won't be nearly as simple as in Javascript. For example, if you wanted to set the private field of an object to something, you could use this function:
并不真地。你可以使用反射来实现你想要的,但它不会像在 Javascript 中那么简单。例如,如果你想将一个对象的私有字段设置为某物,你可以使用这个函数:
protected static void SetField(object o, string fieldName, object value)
{
FieldInfo field = o.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.NonPublic);
field.SetValue(o, value);
}
回答by MojoFilter
All of that would definitely work. Personally, for that particular problem, I would probably take a little different approach. Maybe something like this:
所有这些肯定会奏效。就个人而言,对于那个特定问题,我可能会采取一些不同的方法。也许是这样的:
class MyClass {
public Point point1, point2, point3;
private Point[] points;
public MyClass() {
//...
this.points = new Point[] {point1, point2, point3};
}
public void DoSomethingWith(int i) {
Point target = this.points[i+1];
// do stuff to target
}
}
When using patterns like this, you have to be careful that your data is stored by reference and not by value. In other words, don't do this with primitives. You have to use their big bloated class counterparts.
当使用这样的模式时,你必须小心你的数据是按引用而不是按值存储的。换句话说,不要对原语这样做。你必须使用他们臃肿的类同行。
I realized that's not exactly the question, but the question has been pretty well answered and I thought maybe an alternative approach might help.
我意识到这不完全是问题,但这个问题已经得到很好的回答,我想也许另一种方法可能会有所帮助。
回答by Sébastien Ros - MSFT
I don't now if you absolutely want to execute C# statements, but you can already execute Javascript statements in C# 2.0. The open-source library Jintis able to do it. It's a Javascript interpreter for .NET. Pass a Javascript program and it will run inside your application. You can even pass C# object as arguments and do automation on it.
如果您绝对想执行 C# 语句,我现在不知道,但是您已经可以在 C# 2.0 中执行 Javascript 语句。开源库Jint能够做到这一点。它是 .NET 的 Javascript 解释器。传递一个 Javascript 程序,它将在您的应用程序中运行。您甚至可以将 C# 对象作为参数传递并对其进行自动化。
Also if you just want to evaluate expression on your properties, give a try to NCalc.
此外,如果您只想评估属性的表达式,请尝试NCalc。
回答by Xodem
You also could implement a Webbrowser, then load a html-file wich contains javascript.
您也可以实现一个 Webbrowser,然后加载一个包含 javascript 的 html 文件。
Then u go for the document.InvokeScript
Method on this browser. The return Value of the eval function can be catched and converted into everything you need.
然后你去document.InvokeScript
这个浏览器上的方法。可以捕获 eval 函数的返回值并将其转换为您需要的所有内容。
I did this in several Projects and it works perfectly.
我在几个项目中做到了这一点,而且效果很好。
Hope it helps
希望能帮助到你
回答by xnaterm
Unfortunately, C# doesn't have any native facilities for doing exactly what you are asking.
不幸的是,C# 没有任何本机设施可以完全满足您的要求。
However, my C# eval program 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.
但是,我的 C# eval 程序允许评估 C# 代码。它提供在运行时评估 C# 代码并支持许多 C# 语句。实际上,此代码可在任何 .NET 项目中使用,但仅限于使用 C# 语法。查看我的网站http://csharp-eval.com了解更多详细信息。
回答by Largo
This is an eval function under c#. I used it to convert anonymous functions (Lambda Expressions) from a string. Source: http://www.codeproject.com/KB/cs/evalcscode.aspx
这是c#下的eval函数。我用它从字符串转换匿名函数(Lambda 表达式)。来源:http: //www.codeproject.com/KB/cs/evalcscode.aspx
public static object Eval(string sCSCode) {
CSharpCodeProvider c = new CSharpCodeProvider();
ICodeCompiler icc = c.CreateCompiler();
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", MessageBoxButtons.OK,
MessageBoxIcon.Error );
return null;
}
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 roft
the correct answer is you need to cache all the result to keep the mem0ry usage low.
正确答案是您需要缓存所有结果以保持较低的内存使用率。
an example would look like this
一个例子看起来像这样
TypeOf(Evaluate)
{
"1+1":2;
"1+2":3;
"1+3":5;
....
"2-5":-3;
"0+0":1
}
and add it to a List
并将其添加到列表中
List<string> results = new List<string>();
for() results.Add(result);
save the id and use it in the code
保存id并在代码中使用
hope this helps
希望这可以帮助