我当前正在编写一个应用程序,该应用程序当前通过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语法Tree = sourceLanguage.ParseText(sourceCode,SourceCodeKind.Regular);
var options = new CSharpCompilationOptions(
    OutputKind.DynamicallyLinkedLibrary,
    OptimizationLevel:OptimizationLevel.Debug,
    allowUnsafe:正确
);

CSharpCompilation编译= CSharpCompilation.Create(“ ExampleAssembly”,options:options);

var stream = new MemoryStream();
var结果=编译。
    AddReferences(metaDatareferences)
    .AddSyntaxTrees(syntaxTree)
    .Emit(stream);

//成功是错误的
如果(!emitResult.Success)
{
    foreach(emitResult.Diagnostics中的var诊断)
    {
        Debug.WriteLine(diagnostic.ToString());
    }
}


Debug.WriteLine的输出为:

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


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

使用MediatR;

命名空间ConsoleApplication
{
    公共课程
    {
        公共静态无效的Main(string [] args)
        {
            var mediator = new Mediator(null,null);
        }
    }
}


我的问题是,罗斯林是否提供API以自动加载文件可能具有的任何依赖关系?我希望罗斯林(Roslyn)工作区能够完成此操作,但是我什么都没找到。

最佳答案

如果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

希望能有所帮助。

08-04 10:15