使用Roslyn API编译.NET Core应用程序

4
我正在生成一些动态的C#代码,并希望将其编译为.NET Core应用程序。但是,似乎缺少deps.json文件,以使其实际可运行。 因此,编译本身可以工作,但在运行dotnet [dll名称]时会出现错误:
在代码中,我这样做:
  CSharpCompilation compilation = CSharpCompilation.Create(assemblyName,
    syntaxTrees: files,
    references: references,
    options: new CSharpCompilationOptions(OutputKind.ConsoleApplication,
      optimizationLevel: OptimizationLevel.Debug
    )
  );

  FileUtility.CreateDirectory(outputDllPath);
  EmitResult result = compilation.Emit(outputDllPath, pdbPath: outputPdbPath);

引用集合包含Microsoft.NETCore.App和netstandard 2.0.0 ref dll,以及其他符合netstandard2.0的特定dll。

这可以无错误地工作。运行时我得到:

Unhandled Exception: System.TypeLoadException: Could not load type 'System.Object' from assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

如何为我的编译生成正确的deps.json文件?

我不熟悉CSharpCompilation.Create,它是否实际编译,还是编译/评估发生在Emit上? - Hexo
@SlapY 编译发生在 Emit 上。 - Michiel Overeem
@MattWarren 这很奇怪,因为在Visual Studio中编译的NetCoreApp不需要那个(它可以使用.deps.json工作)。 - Michiel Overeem
请贴出参考文献? - Hexo
1
@MichielOvereem 当你使用Visual Studio构建时,你有一个构建系统(msbuild),它会找出所有依赖程序集的位置,并将这些文件路径提供给编译器。当你使用Roslyn Compilation API时,你必须自己完成这项工作。如果你尝试直接调用csc.exe在命令行上编译应用程序,情况也是如此。 - Matt Warren
显示剩余4条评论
1个回答

3
我们通过以下方法解决了这个问题:
编译C#文件,使用来自C:\ Program Files \ dotnet \ sdk \ NuGetFallbackFolder \ microsoft.netcore.app \ 2.0.0 \ ref \ netcoreapp2.0的dll进行编译(不要添加对.NET 4的引用。dll!):
public static IEnumerable<PortableExecutableReference> CreateNetCoreReferences()
{
  foreach(var dllFile in Directory.GetFiles(@"C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.netcore.app\2.0.0\ref\netcoreapp2.0", "*.dll"))
  {
    yield return MetadataReference.CreateFromFile(dllFile);
  }
}

使用控制台应用程序作为输出,创建一个CSharpCompilation:
CSharpCompilation.Create(assemblyName,
    syntaxTrees: files,
    references: references,
    options: new CSharpCompilationOptions(OutputKind.ConsoleApplication)
  );

现在您只需要将 runtimeconfig.json ([dllname].runtimeconfig.json) 放置到输出文件旁边,并填写以下内容:
{
  "runtimeOptions": {
    "tfm": "netcoreapp2.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "2.0.0"
    }
  }
}

输出结果可以使用 dotnet.exe 运行。

有没有想法如何使用类库输出类型来完成这个?我正在尝试为AWS Lambda构建部署文件。我使用代码片段获取依赖项,但无法构建为ConsoleApplication。 - Timothy Gonzalez
嗨@TimothyGonzalez,你是什么意思?如果你将OutputKind更改为classlibrary,它就会起作用。你只需要找到正确的依赖项集(NetStandard.dll或完整框架的mscorlib)。 - Michiel Overeem
我可以使用 OutputKind.DynamicallyLinkedLibrary 构建项目,但是没有 deps.json 文件。你在使用哪些包?我正在从 .net 4.7 运行时构建 .netcore 1.0。我甚至尝试将其构建为控制台应用程序,但仍然没有 deps.json。最终我只能通过编程方式调用 dotnet build 命令来解决问题。 - Timothy Gonzalez
{btsdaf} - Michiel Overeem
谢谢 @MichielOvereem。现在我可以使用 console.writeline,但是引用任何mvc对象都不起作用 C:\Program Files\dotnet\sdk\NuGetFallbackFolder\microsoft.aspnetcore.mvc.core\2.0.0\lib\netstandard2.0。有什么想法吗? - Thom Kiesewetter
1
当使用vs2017的输出时,它会显示带有所有引用的csc命令。有了这些引用,它将编译。 - Thom Kiesewetter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接