首页 文章

使用Roslyn进行编译时自动解析依赖关系

提问于
浏览
3

我目前正在编写一个当前通过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工作区能够完成这项工作,但我找不到任何东西 .

1 回答

  • 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 .

    希望有所帮助 .

相关问题