2017-01-10 80 views
3

我目前正在编写一个应用程序,该应用程序目前通过Roslyn的工作区API加载项目,将指定的C#文件转换为语法树,然后创建一个内存汇编形式,然后最终提取IL 。使用Roslyn编译时自动解决依赖关系

这一切都工作正常,但只要我参考上述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?) 

我的罗斯林项目读取文件很简单:

 
using MediatR; 

namespace ConsoleApplication 
{ 
    public class Program 
    { 
     public static void Main(string[] args) 
     { 
      var mediator = new Mediator(null, null); 
     } 
    } 
} 

我的问题是,Roslyn会提供一个API来自动加载文件可能具有的任何依赖关系?我希望Roslyn工作区能够完成这个任务,但我一直没能找到任何东西。

+0

您确定这是由于无法加载参考文件,而不是一些语法错误?向我们显示确切的编译器错误。 –

+0

我已更新我的问题以包含错误输出和正在阅读的文件。 –

+0

所以,你希望'使用MediatR'指令可以解决你的lib?这就是为什么你在CSharpScript中有#r 。即使'MetadataReferences'需要解析,请参阅 [MetadataReferenceResolver](http://source.roslyn.io/#Microsoft.CodeAnalysis/MetadataReference/MetadataReferenceResolver.cs,4d808b77e09b1008)。他们只能实现这一点,我能想到的是#1编译,#2检查已知错误,尝试添加引用,转到#1。但即使这样做不适用于扩展方法等,共享一个命名空间... – m0sa

回答

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

希望有所帮助。

+1

完美,“ProjectJsonWorkspace”正是我所期待的,谢谢! –