forked from svg-net/SVG
-
Notifications
You must be signed in to change notification settings - Fork 0
Roslyn
H1Gdev edited this page Jun 13, 2022
·
23 revisions
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
var source = @"
using System;
namespace ConsoleApp
{
internal class Program
{
static void Main()
{
Console.WriteLine(""Hello, World!"");
}
}
}
";
var sourceText = SourceText.From(source, System.Text.Encoding.UTF8);
var options = CSharpParseOptions.Default
.WithLanguageVersion(LanguageVersion.LatestMajor);
var syntaxTree = CSharpSyntaxTree.ParseText(
#if false
// use string.
source,
#else
// use SourceText.
sourceText,
#endif
options
)
.WithFilePath(Path.Combine(sourcePath, "Program.cs"));
var runtimeDirectoryPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory();
var references = new MetadataReference[]
{
MetadataReference.CreateFromFile(typeof(object).Assembly.Location),
MetadataReference.CreateFromFile(Path.Combine(runtimeDirectoryPath, "mscorlib.dll")),
MetadataReference.CreateFromFile(Path.Combine(runtimeDirectoryPath, "System.Runtime.dll")),
// add References if needed.
MetadataReference.CreateFromFile(Path.Combine(runtimeDirectoryPath, "System.Console.dll")),
};
// target framework depends on using libraries.
var entryAssemblyPath = System.Reflection.Assembly.GetEntryAssembly()?.Location ?? string.Empty;
var callingAssemblyPath = System.Reflection.Assembly.GetCallingAssembly()?.Location ?? string.Empty;
var executingAssemblyPath = System.Reflection.Assembly.GetExecutingAssembly()?.Location ?? string.Empty;
var compilationOptions = new CSharpCompilationOptions(OutputKind.ConsoleApplication)
.WithOptimizationLevel(OptimizationLevel.Release)
// if needed.
.WithUsings(new[] { "System.IO" }); // used only in scripting ??
var compilation = CSharpCompilation.Create(
"ConsoleApp",
// source code(s).
new[] { syntaxTree },
references,
compilationOptions);
var assemblyFile = $"{compilation.AssemblyName}.{(compilationOptions.OutputKind == OutputKind.ConsoleApplication ? "exe" : "dll")}";
var assemblyPath = Path.Combine(buildPath, assemblyFile);
var emitResult = compilation.Emit(assemblyPath);
using var stream = new MemoryStream();
var emitResult = compilation.Emit(stream);
foreach (var diagnostic in emitResult.Diagnostics)
{
#if false
var pos = diagnostic.Location.GetLineSpan();
var location = $"{pos.Path}({pos.StartLinePosition.Line + 1},{pos.StartLinePosition.Character + 1})";
Console.WriteLine($"{location}: {diagnostic.Severity} {diagnostic.Id}: {diagnostic.GetMessage()}");
#else
// use DiagnosticFormatter internally.
Console.WriteLine(diagnostic);
#endif
}
if (!emitResult.Success)
throw new InvalidProgramException("Compile error occured.");
using System.Reflection;
#if !NETFRAMEWORK
using System.Runtime.Loader;
#endif
#if NETFRAMEWORK
var assembly = Assembly.LoadFrom(assemblyPath);
#else
var assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);
#endif
stream.Seek(0, SeekOrigin.Begin);
#if NETFRAMEWORK
var assembly = Assembly.Load(stream.ToArray());
#else
var assembly = AssemblyLoadContext.Default.LoadFromStream(stream);
#endif
#if !NETFRAMEWORK
var assemblyLoadContext = new AssemblyLoadContext(compilation.AssemblyName, true);
try
{
// load from assemblyLoadContext.
}
finally
{
assemblyLoadContext.Unload();
}
#endif
- If unload assembly.
var type = assembly.GetType("ConsoleApp.Program");
var method = type?.GetMethod("Main", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
method?.Invoke(null, null);