我可以做一個eval("something()");
在JavaScript中動態執行代碼。有沒有辦法讓我在C#中做同樣的事情?如何動態評估C#代碼?
我正在嘗試做的是,我有一個整型變量(說i
),我有名稱的多個屬性:「Property1」,「Property2」,「Property3」等。 現在,我想要根據i
的值對「屬性i」屬性執行一些操作。
這對於JavaScript來說非常簡單。有沒有辦法與C#做到這一點?
我可以做一個eval("something()");
在JavaScript中動態執行代碼。有沒有辦法讓我在C#中做同樣的事情?如何動態評估C#代碼?
我正在嘗試做的是,我有一個整型變量(說i
),我有名稱的多個屬性:「Property1」,「Property2」,「Property3」等。 現在,我想要根據i
的值對「屬性i」屬性執行一些操作。
這對於JavaScript來說非常簡單。有沒有辦法與C#做到這一點?
不幸的是,C#是不是這樣的動態語言。然而,你可以做的是創建一個C#源代碼文件,該文件充滿了類和所有內容,並通過CodeDom提供程序運行C#並將其編譯爲程序集,然後執行它。
這在MSDN論壇帖子包含一些示例代碼下來有些頁面的答案:
create a anonymous method from a string?
我很難說這是一個很好的解決方案,但它是可能無妨。
你會期待什麼樣的代碼在字符串中?如果它是有效代碼的次要子集,例如只是數學表達式,則可能存在其他替代方案。
編輯:好了,教我徹底先讀問題。是的,反思能夠在這裏給你一些幫助。
如果你用字符串分割字符串;首先,要獲取單個屬性,可以使用以下代碼爲某個類的特定屬性獲取PropertyInfo對象,然後使用該對象來操作特定對象。
String propName = "Text";
PropertyInfo pi = someObject.GetType().GetProperty(propName);
pi.SetValue(someObject, "New Value", new Object[0]);
您可以使用反射來獲取屬性並調用它。事情是這樣的:
object result = theObject.GetType().GetProperty("Property" + i).GetValue(theObject, null);
也就是說,假設有屬性被稱爲「theObject」的對象:)
你可以用原型函數做到這一點:
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);
}
等上...
不是。你可以使用反射來達到你想要的效果,但它不會像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);
}
所有這一切肯定會工作。就個人而言,對於那個特定的問題,我可能會採取一些不同的方法。也許是這樣的:
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
}
}
當使用模式就是這樣,你要小心,你的數據存儲引用而不是價值。換句話說,不要用原語做這件事。你必須使用他們臃腫的類同行。
我意識到這不完全是問題,但問題已得到很好的回答,我想也許有其他方法可以幫助。
你也可以實現一個Webbrowser,然後加載一個包含javascript的html文件。
然後你去這個瀏覽器的document.InvokeScript
方法。 eval函數的返回值可以被捕獲並轉換爲您需要的所有內容。
我在幾個項目中做了這個,它的功能完美。
希望它可以幫助
不幸的是,C#不具備做的正是你所要求的任何本地設施。
但是,我的C#eval程序確實允許評估C#代碼。它提供了在運行時評估C#代碼並支持許多C#語句。實際上,這個代碼可以在任何.NET項目中使用,但是它僅限於使用C#語法。看看我的網站,http://csharp-eval.com,瞭解更多詳情。
看一看[羅斯林腳本API](https://github.com/dotnet/roslyn/wiki/Scripting-API-Samples) – 2017-10-22 16:23:42
這是一個在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;
}
@sehe糟糕,我糾正了錯字(倫巴達=> LAMBDA)。我不知道這首歌叫做Lambada,所以這是一個無意的故事。 ;) – Largo 2011-12-23 22:47:03
正確的答案是,你需要緩存所有的結果保持mem0ry使用率較低。
一個例子是這樣的
TypeOf(Evaluate)
{
"1+1":2;
"1+2":3;
"1+3":5;
....
"2-5":-3;
"0+0":1
}
,並把它添加到列表
List<string> results = new List<string>();
for() results.Add(result);
保存ID,並在代碼中使用它
希望這有助於
在運行時使用反射來解析和評估針對對象的數據綁定表達式。
我寫了一個開源項目,Dynamic Expresso,可轉換使用C#語法爲代表(或表達式樹)的書面文字表達。表達式被解析並轉換成Expression Trees而不使用編譯或反射。
您可以編寫類似:
var interpreter = new Interpreter();
var result = interpreter.Eval("8/2 + 2");
或
var interpreter = new Interpreter()
.SetVariable("service", new ServiceExample());
string expression = "x > 4 ? service.SomeMethod() : service.AnotherMethod()";
Lambda parsedExpression = interpreter.Parse(expression,
new Parameter("x", typeof(int)));
parsedExpression.Invoke(5);
我的工作是基於斯科特谷的文章http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx。
使用羅斯林腳本API(更多samples here):
// add NuGet package 'Microsoft.CodeAnalysis.Scripting'
using Microsoft.CodeAnalysis.CSharp.Scripting;
await CSharpScript.EvaluateAsync("System.Math.Pow(2, 4)") // returns 16
您也可以運行任何一段代碼:
var script = await CSharpScript.RunAsync(@"
class MyClass
{
public void Print() => System.Console.WriteLine(1);
}")
和參考這是在以前的運行生成的代碼:
await script.ContinueWithAsync("new MyClass().Print();");
我寫了一個包,SharpByte.Dynamic,以簡化任務o f動態編譯和執行代碼。可以使用擴展方法在任何上下文對象上調用該代碼,詳見here。
例如,
someObject.Evaluate<int>("6/{{{0}}}", 3))
返回3;
someObject.Evaluate("this.ToString()"))
返回上下文對象的字符串表示;
someObject.Execute(@
"Console.WriteLine(""Hello, world!"");
Console.WriteLine(""This demonstrates running a simple script"");
");
運行這些語句作爲腳本等
可執行文件可以很容易地利用工廠方法得到,如示例here --all你需要看到的是任何預期的源代碼和列表
IExecutable executable = ExecutableFactory.Default.GetExecutable(executableType, sourceCode, parameterNames, addedNamespaces);
每個可執行的目標:命名參數(令牌使用三重括號標記,如{{{0}}},以避免與的String.format)碰撞(以及把手狀語法嵌入的) (腳本或表達式)是線程安全的,可以存儲d和重複使用,支持從腳本內登錄,存儲定時信息和最後異常,如果遇到等也有複印編譯上的每個,以允許創建廉價複製,即,使用從腳本或表達式編譯的可執行對象()方法作爲創建他人的模板。
執行的已編譯腳本或語句的開銷比較低,遠低於一般硬體上一微秒,並且已經編譯腳本和表達式緩存重用。
C#調用IronPython中的eval。我在c#4.0中試過。用C#2.0 – 2011-05-15 03:00:56
@Peter龍沒有經驗,我在哪裏可以找到文檔上的IronPython的eval? – smartcaveman 2011-06-16 16:09:41
看看[Mono的CSHARP交互的shell(http://www.mono-project.com/CsharpRepl)。它具有[eval-like functions](http://www.go-mono.com/docs/index.aspx?link=N:Mono.CSharp)。 – 2011-02-27 20:28:24