我正在编写一个当前通过Roslyn的工作空间API加载项目的应用程序,将指定的C#文件转换为语法树然后创建一个内存汇编形式,然后最终提取IL。
这一切都运行正常,但是当我引用所述C#文件中的任何外部库时,编译失败,因为Roslyn不知道在哪里解析这些引用。
以下是我目前正在做的简化版本:
MetadataReference[] metaDatareferences = { 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, optimizationLevel: OptimizationLevel.Debug, allowUnsafe: true ); CSharpCompilation compilation = CSharpCompilation.Create("ExampleAssembly", options: options); var stream = new MemoryStream(); var result = compilation. AddReferences(metaDatareferences) .AddSyntaxTrees(syntaxTree) .Emit(stream); // Success is false if (!emitResult.Success) { foreach (var diagnostic in emitResult.Diagnostics) { Debug.WriteLine(diagnostic.ToString()); } }
Debug.WriteLine
的输出是:
(1,7): error CS0246: The type or namespace name 'MediatR' could not be found (are you missing a using directive or an assembly reference?) (9,32): error CS0246: The type or namespace name 'Mediator' could not be found (are you missing a using directive or an assembly reference?)
我的Roslyn项目正在阅读的文件就是这样:
using MediatR; namespace ConsoleApplication { public class Program { public static void Main(string[] args) { var mediator = new Mediator(null, null); } } }
我的问题是,Roslyn是否提供了一个API来自动加载文件可能具有的任何依赖项?我希望Roslyn工作区能够完成这项工作,但我找不到任何东西。
答案 0 :(得分:1)
如果MediatR控制台项目是project.json
项目,那么您可以使用ProjectJsonWorkspace
中的"Microsoft.DotNet.ProjectModel.Workspaces": "1.0.0-preview2-1-003177"
。您可以将它指向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
。
希望有所帮助。