【问题标题】:Automatically resolving dependencies when compiling using Roslyn使用 Roslyn 编译时自动解析依赖关系
【发布时间】:2017-05-24 17:21:14
【问题描述】:

我目前正在编写一个应用程序,该应用程序当前通过 Roslyn 的工作区 API 加载项目,将指定的 C# 文件转换为语法树,然后从它创建一个内存程序集,然后最终提取 IL。

这一切正常,但是只要我在所述 C# 文件中引用任何外部库,编译就会失败,因为 Roslyn 不知道在哪里解析这些引用。

这是我目前正在做的简化版本:

元数据引用 [] 元数据引用 = { MetadataReference.CreateFromFile(typeof(object).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(Uri).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(DynamicAttribute).GetTypeInfo().Assembly.Location), MetadataReference.CreateFromFile(typeof(AssemblyMetadata).GetTypeInfo().Assembly.Location), }; var sourceLanguage = new CSharpLanguage(); var syntaxTree = sourceLanguage.ParseText(sourceCode, SourceCodeKind.Regular); var options = new CSharpCompilationOptions( OutputKind.DynamicallyLinkedLibrary, 优化级别:优化级别。调试, 允许不安全:真 ); CSharpCompilation 编译 = CSharpCompilation.Create("ExampleAssembly", options: options); var 流 = 新的 MemoryStream(); var 结果 = 编译。 添加引用(元数据引用) .AddSyntaxTrees(syntaxTree) .Emit(流); // 成功为假 如果(!emitResult.Success) { foreach(emitResult.Diagnostics 中的 var 诊断) { Debug.WriteLine(diagnostic.ToString()); } }

Debug.WriteLine 的输出是:

(1,7):错误 CS0246:找不到类型或命名空间名称“MediatR”(您是否缺少 using 指令或程序集引用?) (9,32):错误 CS0246:找不到类型或命名空间名称“Mediator”(您是否缺少 using 指令或程序集引用?)

我的 Roslyn 项目正在读取的文件就是这样的:

使用 MediatR; 命名空间控制台应用程序 { 公开课程序 { 公共静态无效主要(字符串[]参数) { var mediator = new Mediator(null, null); } } }

我的问题是,Roslyn 是否提供 API 来自动加载文件可能具有的任何依赖项?我希望 Roslyn 工作区允许这样做,但我找不到任何东西。

【问题讨论】:

  • 你确定这是由于无法加载引用,而不是例如一些语法错误?向我们展示确切的编译器错误。
  • 我已经更新了我的问题以包含错误输出和我正在阅读的文件。
  • 那么,您希望using MediatR; 指令能够解析您的库吗?这就是 CSharpScript 中有 #r <path> 的原因。甚至MetadataReferences 也需要解决,参见MetadataReferenceResolver。我能想到的实现这一点的唯一方法是#1 编译,#2 检查已知错误,尝试添加引用,转到#1。但即使这样也不适用于共享命名空间的扩展方法等......
  • @m0sa 不,这不是 C# 脚本文件。我的意图是编译从项目工作区中提取的随机 C#。
  • 当您说您正在“从项目”加载文件时,您是否有 .csproj 或 project.json 或其他东西可供查看?

标签: c# .net .net-core roslyn


【解决方案1】:

如果 MediatR 控制台项目是 project.json 项目,那么您可以使用来自 "Microsoft.DotNet.ProjectModel.Workspaces": "1.0.0-preview2-1-003177" 的 ProjectJsonWorkspace。您可以将它指向您的project.json 并获得一个Compilation 对象,这将为您完成获取项目引用、文件引用等的所有艰苦工作......然后您可以从这里发出您的IL。

这是一个例子:

var compilation = new ProjectJsonWorkspace(@"PathToYour\project.json").CurrentSolution.Projects.First().GetCompilationAsync().Result;

var stream = new MemoryStream();
var emitResult = compilation.Emit(stream);

或者如果您需要完全控制,您可以继续使用CSharpCompilation.Create,从此处的compilation 对象中复制您需要的内容,并传入SyntaxTree。

希望对您有所帮助。

【讨论】:

  • 完美,ProjectJsonWorkspace 正是我想要的,谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-04-29
  • 1970-01-01
相关资源
最近更新 更多