I'm using Roslyn to compile strings of C# code. I'd like to use the output of one of the compilations as metadata reference for another, but when I try to invoke a method that forces the loading of the referenced assembly, I get an ImageNotFoundException, complaining that the referenced assembly (MyReference.dll in the sample case) could not be found. This is the minified version of my problem:
internal class Program
{
public static MemoryStream CompileCSharp(
string assemblyName,
string code,
params MetadataReference[] additionalReferences)
{
var sourceText = SourceText.From(code, Encoding.UTF8);
var tree = SyntaxFactory.ParseSyntaxTree(sourceText);
var defaultReferences = Basic.Reference.Assemblies.Net70.ReferenceInfos.All
.Select(r => MetadataReference.CreateFromStream(new MemoryStream(r.ImageBytes)));
var compilation = CSharpCompilation.Create(
assemblyName: assemblyName,
syntaxTrees: new[] { tree },
references: defaultReferences.Concat(additionalReferences),
options: new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
var stream = new MemoryStream();
var emitResult = compilation.Emit(stream);
Debug.Assert(emitResult.Success);
stream.Position = 0;
return stream;
}
static void Main(string[] args)
{
var referenceBytes = CompileCSharp(
"MyReference.dll",
"""
public class IdentityProvider
{
public T Identity<T>(T x) => x;
}
""");
var reference = MetadataReference.CreateFromStream(referenceBytes);
var mainAssembly = CompileCSharp(
"Main.dll",
"""
using System;
public class Program
{
public static void Main()
{
var provider = new IdentityProvider();
Console.WriteLine(provider.Identity(123));
}
}
""",
reference);
var asm = Assembly.Load(mainAssembly.ToArray());
asm.GetType("Program")!.GetMethod("Main")!.Invoke(null, null);
}
}
The references I use:
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.6.0-1.final" />(Roslyn itself)<PackageReference Include="Basic.Reference.Assemblies.Net70" Version="1.4.1" />(to not have to deal with metadata management of .NET Core)
Without referencing anything, a hello world program compiles fine, making me believe that there is some runtime quirk I do not know about, like requiring the file to be on disk or something. However, I could not verify this.