使用 Roslyn 编译时自动解决依赖关系
Automatically resolving dependencies when compiling using Roslyn
我目前正在编写一个应用程序,该应用程序当前通过 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 工作区能够完成此操作,但我一直找不到任何东西。
如果 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
.
希望对您有所帮助。
我目前正在编写一个应用程序,该应用程序当前通过 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 工作区能够完成此操作,但我一直找不到任何东西。
如果 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
.
希望对您有所帮助。