我正在尝试编写一个交互式 C# 教学应用程序,用户可以在其中实验/更改代码示例并看看会发生什么(有点像 jsfiddle)。
我找到了很多小表达式或类似 REPL 的使用 Mono.Csharp 作为运行时编译器的示例,但我找不到执行“小程序”的示例。
这是迄今为止我的玩具代码(MVC 操作)。 “code”参数直接从文本区域发布。
[HttpPost]
public ActionResult Index(string code)
{
var reportWriter = new StringWriter();
var settings = new CompilerSettings();
var printer = new ConsoleReportPrinter(reportWriter);
var reports = new Report(printer);
var eval = new Evaluator(settings, reports);
var model = new CodeViewModel();
model.Code = code;
eval.Run(code);
model.Result = reportWriter.ToString();
return View("Index", model);
}
现在假设代码是这样的字符串:
using System;
public class MyClass
{
public void DoSomething()
{
Console.WriteLine("hello from DoSomething!");
}
}
如何引导它(即实例化一个
MyClass
对象并在其上调用 DoSomething
)?我尝试在末尾添加 new MyClass().DoSomething();
,但我得到了这个:
{interactive}(1,2): warning CS0105: The using directive for `System' appeared previously in this namespace
{interactive}(1,8): (Location of the symbol related to previous warning)
{interactive}(11,1): error CS1530: Keyword `new' is not allowed on namespace elements
{interactive}(11,4): error CS1525: Unexpected symbol `MyClass', expecting `class', `delegate', `enum', `interface', `partial', or `struct'
我错过了什么?
var reportWriter = new StringWriter();
var settings = new CompilerSettings();
var printer = new ConsoleReportPrinter(reportWriter);
var reports = new Report(printer);
var eval = new Evaluator(settings, reports);
eval.Run(code);
eval.Run(@"
var output = new System.IO.StringWriter();
Console.SetOut(output);
new MyClass().DoSomething();");
var model = new CodeViewModel();
model.Code = code;
if (reports.Errors > 0)
model.Result = reportWriter.ToString();
else
model.Result = (string) eval.Evaluate("output.ToString();");
return View("Index", model);
虽然这个问题已经被接受,但当我看到这篇文章时我也遇到了类似的问题。 我终于弄清楚了,所以我想我应该在这里发帖,以防其他人遇到麻烦。
您不能在对
using
的同一调用中混合使用 Evaluator
和其他语句。 来自 Mono.CSharp REPL 上的文档:
using 声明必须单独出现,不能与常规语句混合在一行中。
由于这是对每行的
Evaluator
进行单独调用,因此同样的限制也适用于从应用程序调用 Evaluator
。