I am attempting to dynamically compile code and execute it in runtime. So I followed http://www.tugberkugurlu.com/archive/compiling-c-sharp-code-into-memory-and-executing-it-with-roslyn as a guide.
The code given in the example works prefectly. However, if I use Console.ReadKey()
it gives me error CS0117: 'Console' does not contain a definition for 'ReadKey'
. I read somewhere that this is because dotnet core does not support ReadKey
('Console' does not contain a definition for 'ReadKey' in asp.net 5 console App), but I am currently using "Microsoft.NETCore.App"
and it Console.ReadKey()
works perfectly if I use it explicitly in code instead of while using Roslyn.
- Is this an issue with Roslyn or am I doing something wrong?
- Are
"Microsoft.NETCore.App"
anddotnet core
the same thing? I suspect I might be using something else as my target (which allows me to useReadKey
) and dotnet core with Roslyn - Is it possible to change Roslyn's target to something else?
Thanks in advance.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
namespace DemoCompiler
{
class Program
{
public static void roslynCompile()
{
string code = @"
using System;
using System.Text;
namespace RoslynCompileSample
{
public class Writer
{
public void Write(string message)
{
Console.WriteLine(message);
Console.ReadKey();
}
}
}";
SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(code);
string assemblyName = Path.GetRandomFileName();
MetadataReference[] references = new MetadataReference[]
{
MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location),
MetadataReference.CreateFromFile(typeof(Enumerable).GetTypeInfo().Assembly.Location)
};
CSharpCompilation compilation = CSharpCompilation.Create(
assemblyName,
syntaxTrees: new[] { syntaxTree },
references: references,
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
using (var ms = new MemoryStream())
{
EmitResult result = compilation.Emit(ms);
if (!result.Success)
{
IEnumerable<Diagnostic> failures = result.Diagnostics.Where(diagnostic =>
diagnostic.IsWarningAsError ||
diagnostic.Severity == DiagnosticSeverity.Error);
foreach (Diagnostic diagnostic in failures)
Console.Error.WriteLine("{0}: {1}", diagnostic.Id, diagnostic.GetMessage());
}
else
{
ms.Seek(0, SeekOrigin.Begin);
Assembly assembly = AssemblyLoadContext.Default.LoadFromStream(ms);
var type= assembly.GetType("RoslynCompileSample.Writer");
var instance = assembly.CreateInstance("RoslynCompileSample.Writer");
var meth = type.GetMember("Write").First() as MethodInfo;
meth.Invoke(instance, new [] {assemblyName});
}
}
}
}
}
Edit : I tried to reference System.Console.dll
but I got conflict between that and System.Private.CoreLib
. How do I resolve it?