Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Roslyn Scripting API on .NET Core: why does compiler complain "error CS1501: no overload for WriteLine takes 2 arguments"?

I'm working on a project targeting netcoreapp1.0 on OSX, and I'm setting up a script using Roslyn like this:

var scriptText = File.ReadAllText(args[0]);

var scriptOptions = ScriptOptions.Default
    .WithReferences(
        typeof(System.Object).GetTypeInfo().Assembly
    );

var script = CSharpScript.Create(scriptText, scriptOptions, typeof(Globals));

var scriptArgs = new string[args.Length-1];
Array.Copy(args, 1, scriptArgs, 0, args.Length-1);

script.RunAsync(new Globals
{ 
    Args = scriptArgs
})
.GetAwaiter().GetResult();

Where Globals is:

public class Globals
{
    public string[] Args { get; set; }
}

When I try to run a script that looks like this:

using System;

Console.WriteLine("Args[0]: {0}", Args[0]);

The program terminates with this exception:

$ dotnet run test.csx
Project BitThicket.DotNet.ScriptTool (.NETCoreApp,Version=v1.0) was previously compiled. Skipping compilation.
Script error: Microsoft.CodeAnalysis.Scripting.CompilationErrorException: (7,9): error CS1501: No overload for method 'WriteLine' takes 2 arguments
   at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.ThrowIfAnyCompilationErrors(DiagnosticBag diagnostics, DiagnosticFormatter formatter)
   at Microsoft.CodeAnalysis.Scripting.ScriptBuilder.CreateExecutor[T](ScriptCompiler compiler, Compilation compilation, CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Scripting.Script`1.GetExecutor(CancellationToken cancellationToken)
   at Microsoft.CodeAnalysis.Scripting.Script`1.RunAsync(Object globals, Func`2 catchException, CancellationToken cancellationToken)
   at BitThicket.DotNet.ScriptTool.Program.Main(String[] args) in /Users/ben/proj/bt/dotnet-scriptcs/src/BitThicket.DotNet.ScriptTool/Program.cs:line 63

Obviously Console does, in fact, have an overload that takes 2 methods. I looked at the CoreFx sources briefly to see if there were any odd type-forwarding or extension method tricks being used that might need additional care in the script setup, but I didn't see anything unusual there (maybe I missed something).

Why would the Roslyn ScriptBuilder then complain about this?

like image 360
Ben Collins Avatar asked Jul 28 '16 04:07

Ben Collins


1 Answers

In .NET Core, the Console class is in the System.Console assembly, so you'll need to add it to the script's references:

var scriptOptions = ScriptOptions.Default
    .WithReferences(
        typeof(System.Object).GetTypeInfo().Assembly,
        typeof(System.Console).GetTypeInfo().Assembly
    );

If you check the assembly location of Object, you'll see it's System.Private.CoreLib.ni.dll. Using ILSpy, we can see this assembly only contains a basic Console implementation, with the methods Write(string s), WriteLine(string s) and WriteLine(). Whereas the System.Console assembly contains the full implementation.

like image 122
Eli Arbel Avatar answered Nov 15 '22 05:11

Eli Arbel