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 (i.e. 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?
The Mono C# compiler is considered feature complete for C# 1.0, C# 2.0, C# 3.0, C# 4.0, C# 5.0 and C# 6.0 (ECMA) and it has partial support for C# 7.
mcs is the Mono C# compiler, an implementation of the ECMA-334 language specification. You can pass one or more options to drive the compiler, and a set of source files. Extra options or arguments can be provided in a response file. Response files are referenced by prepending the @ symbol to the response file name.
About CompilingThe amazing part of the coding process is the compiler. The compiler takes the text that you've written and will convert it to machine code (in the case of languages such as C++) or an intermediary language that can be executed by a Just In Time Compiler (in the case of languages such as C# and Java).
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With