System.TypeLoadException: Could not load type 'System.Object' from assembly 'System.Private.CoreLib' because the parent does not exist
Asked Answered
P

1

6

We are generating code dynamically to produce a .NET Core console application and then compiling it using:

    var csharpParseOptions = new CSharpParseOptions(LanguageVersion.Latest);

    csharpParseOptions = csharpParseOptions.WithPreprocessorSymbols(new[] { "TRACE", "DEBUG" });

    var syntaxTree = CSharpSyntaxTree.ParseText(code, options: csharpParseOptions);
    var compilationUnitSyntax = syntaxTree.GetCompilationUnitRoot();

    var options = new CSharpCompilationOptions(OutputKind.ConsoleApplication, optimizationLevel: OptimizationLevel.Debug, platform: Platform.X64)
      .WithModuleName("TestConsole")
      .WithMetadataImportOptions(MetadataImportOptions.All)
      .WithDeterministic(true)
      .WithConcurrentBuild(true);

    var csharpCompilation = CSharpCompilation.Create(@"TestConsole", syntaxTrees: new[] { syntaxTree }, references: references, options: options);

We can then work without any problems against the generated assembly (in memory) obtained using:

    using (var memoryStream = new MemoryStream())
    {
      var emitResult = csharpCompilation.Emit(memoryStream);
      memoryStream.Position = 0; 
      _assembly = Assembly.Load(memoryStream.ToArray());
    }

However, when we write the console.exe to disk using:

    csharpCompilation.Emit(fileNameOnDisk, Path.Combine(Path.GetDirectoryName(fileNameOnDisk), Path.GetFileNameWithoutExtension(fileNameOnDisk)) + ".pdb");

and try to run it from there we get the following exception:

System.TypeLoadException: Could not load type 'System.Object' from assembly 'System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e' because the parent does not exist.

Copying the same generated code (Program.cs) into an empty Console project works perfectly but we notice that the size of the executable is significantly larger.

Does anyone have any ideas how to go about fixing this problem? Thanks.

Phenocryst answered 11/8, 2022 at 17:2 Comment(0)
M
2

I think your problem is the lack of runtime configuration. From what I read above if you add a file named testconsole.runtimeconfig.json with the following info or similar:

{
    "runtimeOptions": {
        "tfm": "net6.0",
        "framework": {
            "name": "Microsoft.NETCore.App",
            "version": "6.0.0"
        }
    }
}

You'll see that it runs. I'm also attaching a complete example with compilation.Emit that I validated in LINQPad. It does not require an additional file since it generates it in the example. Best of luck and hope it is still useful.

var tree = CSharpSyntaxTree.ParseText (@"class Program 
{
    static void Main() => System.Console.WriteLine (""Hello"");
}");

string trustedAssemblies = (string)AppContext.GetData ("TRUSTED_PLATFORM_ASSEMBLIES");
var trustedAssemblyPaths = trustedAssemblies.Split (Path.PathSeparator);
var references = trustedAssemblyPaths.Select (path => MetadataReference.CreateFromFile (path));

var compilation = CSharpCompilation
    .Create ("test")
    .WithOptions (new CSharpCompilationOptions (OutputKind.ConsoleApplication))
    .AddSyntaxTrees (tree)
    .AddReferences (references);

string outputPath = "test.dll";
Path.GetFullPath (outputPath).Dump();
EmitResult result = compilation.Emit (outputPath);
Console.WriteLine (result.Success);

File.WriteAllText ("test.runtimeconfig.json", @$"{{
    ""runtimeOptions"": {{
        ""tfm"": ""net{Environment.Version.Major}.{Environment.Version.Minor}"",
        ""framework"": {{
            ""name"": ""Microsoft.NETCore.App"",
            ""version"": ""{Environment.Version.Major}.{Environment.Version.Minor}.{Environment.Version.Build}""
        }}
    }}
}}");

// Execute the program we just compiled.
Util.Cmd (@"dotnet.exe", "\"" + Path.GetFullPath (outputPath) + "\"");
Mammy answered 7/1, 2023 at 20:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.