简体   繁体   中英

Running a mini-program in Mono.Csharp

I'm trying to write an interactive C# teaching app, where the user can experiment/change code examples and see what happens (kinda like jsfiddle).

I've found a lot of examples for small expressions or REPL-like uses of Mono.Csharp as runtime compiler, but I can't quite find an example where a "mini program" is executed.

Here's my toy code so far (an MVC action). The "code" parameter is posted straight from a textarea.

[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);
}

Now suppose the code is a string like this:

using System;
public class MyClass
{
    public void DoSomething()
    {
        Console.WriteLine("hello from DoSomething!");
    }
}

How do I bootstrap this (ie instantiate a MyClass object and call DoSomething on it)? I've tried just appending new MyClass().DoSomething(); to the end, but I get this:

{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'

What am I missing?

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);

Although this question has already been accepted, I was having a similar issue when I ran across this post. I finally figured it out, so I thought I'd post here in case someone else runs into trouble.

You cannot mix using 's and other statements in the same call to the Evaluator . From the documentation on the Mono.CSharp REPL:

The using declarations must appear on their own and can not be mixed with regular statements in a single line.

Since this is using individual calls to the Evaluator for each line, this same restriction applies for invoking the Evaluator from your application.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM