在 OSX 上使用 .NET Core 从代码调用 Roslyn:“未找到包含 System.Object 的程序集”

Ben*_*son 1 .net c# macos roslyn .net-core

我正在尝试在 OSX 上的 .NET Core 中从 C# 调用 Roslyn。

public class Program
{
    public static void Main()
    {
        var cscArgs = CSharpCommandLineParser.Default.Parse(
            new[] { "/target:Library" },
            Directory.GetCurrentDirectory(),
            "/usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.1.0/"
        );
        var refs = cscArgs.MetadataReferences.Select(x => MetadataReference.CreateFromFile(x.Reference, x.Properties));

        foreach (var r in refs)
        {
            Console.WriteLine(r.FilePath);
        }

        var trees = new[]
        {
            CSharpSyntaxTree.ParseText("class Foo {}", cscArgs.ParseOptions)
        };

        var compilation = CSharpCompilation.Create(cscArgs.CompilationName, trees, refs, cscArgs.CompilationOptions);

        using (var peStream = File.OpenWrite("test.dll"))
        {
            var emitResult = compilation.Emit(peStream, null, null, null, cscArgs.ManifestResources, cscArgs.EmitOptions);

            foreach (var d in emitResult.Diagnostics)
            {
                Console.WriteLine(d);
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当我运行此代码时, (test.dll保持为空并且) WriteLines 打印出一个,MetadataReference然后是一个警告和两个编译错误:

/usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.1.0/mscorlib.dll
warning CS8021: No value for RuntimeMetadataVersion found. No assembly containing System.Object was found nor was a value for RuntimeMetadataVersion specified through options.
(2,31): error CS0518: Predefined type 'System.Object' is not defined or imported
(2,31): error CS1729: 'object' does not contain a constructor that takes 0 arguments
Run Code Online (Sandbox Code Playgroud)

所以看起来Compilation没有拿起mscorlib参考。DLL 确实存在于引用的位置。

$ ls /usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.1.0/mscorlib.dll
/usr/local/share/dotnet/shared/Microsoft.NETCore.App/1.1.0/mscorlib.dll
Run Code Online (Sandbox Code Playgroud)

我究竟做错了什么?我怎样才能说服 Roslyn 拿起mscorlibDLL?

nat*_*ter 5

如果您尝试为 .NET Core 编译程序集,System.Object则在 中定义System.Runtime,而不是 mscorlib。1此外,在为 .NET Core 编译时,编译器通常使用引用程序集,而不是实际的运行时二进制文件。

所以,简短的回答:为 System.Runtime.dll 创建 MetadataReference。

var nuget = Environment.GetEnvironmentVariable("HOME") + "/.nuget/packages";
MetadataReference.CreateFromFile(nuget + "/system.runtime/4.3.0/ref/netstandard1.5/System.Runtime.dll")
Run Code Online (Sandbox Code Playgroud)

更长的答案

不过,很有可能您不仅需要 System.Runtime。查看正在引用哪些库的更简单方法是检查您自己的应用程序的编译。要查看这一点,请添加一个包引用Microsoft.Extensions.DependencyModel并检查用于编译和应用程序的所有库。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp1.1</TargetFramework>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="2.0.0-*" />
    <PackageReference Include="Microsoft.Extensions.DependencyModel" Version="1.1.0" />
  </ItemGroup>

</Project>
Run Code Online (Sandbox Code Playgroud)
var references = from l in DependencyContext.Default.CompileLibraries
                 from r in l.ResolveReferencePaths()
                 select MetadataReference.CreateFromFile(r);

foreach (var r in references)
{
    Console.WriteLine(r.FilePath);
}
Run Code Online (Sandbox Code Playgroud)

1请参阅页面最底部的https://docs.microsoft.com/en-us/dotnet/core/api/system.object