JavaScript 的 eval() 能在執行期動態解析並執行字串程式碼,極適合規則引擎、使用者自訂腳本、動態報表等場景。C# 作為靜態編譯語言雖無內建 Eval,但透過 System.CodeDom.Compiler 命名空間,可在執行期動態編譯 C# 程式碼並呼叫,達到相同效果。
CSharpCodeProvider 在記憶體中編譯組件 (GenerateInMemory = true)。Assembly.GetType() 取得動態類別,再用 InvokeMember 呼叫目標方法。using System;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.Reflection;
namespace CSHARP_EVAL_FUNCTION {
public class EVAL {
private static string prefix = @"
using System;
public static class DynamicClass {
public static void Bomb() {";
private static string postfix = @"}}";
public string Content { get; set; }
public void Eval() {
if (string.IsNullOrEmpty(Content)) {
Console.WriteLine("必須為 Content 屬性賦予值");
return;
}
string code = prefix + Content + postfix;
CompilerResults result = null;
using (var provider = new CSharpCodeProvider()) {
var options = new CompilerParameters {
GenerateInMemory = true,
TreatWarningsAsErrors = false
};
result = provider.CompileAssemblyFromSource(options, code);
if (result.Errors.HasErrors) {
var errorMsg = new StringBuilder();
foreach (CompilerError error in result.Errors) {
errorMsg.AppendFormat("Line:{0}, Column:{1}, Error:{2}\n",
error.Line, error.Column, error.ErrorText);
}
Console.WriteLine("編譯錯誤:\n" + errorMsg);
} else {
Type dynamicClass = result.CompiledAssembly.GetType("DynamicClass");
dynamicClass.InvokeMember("Bomb",
BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.Public,
null, null, null);
}
}
}
}
}
var eval = new EVAL();
eval.Content = @"
Console.WriteLine(""Hello from dynamic code!"");
int x = 10, y = 20;
Console.WriteLine($""Sum: {x + y}"");";
eval.Eval();
// 輸出:
// Hello from dynamic code!
// Sum: 30
public static TResult Eval<TResult>(),搭配 Func<TResult> 委派。AppDomain 或 .NET Core 的 AssemblyLoadContext 限制動態程式碼權限。CSharpScript 取代 CodeDom (已淘汰)。using 陳述式,擴充可用 API。CodeDom 僅支援 .NET Framework;.NET Core / .NET 5+ 請改用 Roslyn Scripting API (Microsoft.CodeAnalysis.CSharp.Scripting),效能更好且支援跨平台。動態編譯涉及安全風險,嚴禁直接執行不可信輸入,生產環境務必實施輸入驗證與沙箱機制。




原始碼下載:CSDN 下載連結