如何使用Roslyn编译C#解决方案?

我有一个软件,可以根据用户操作为C#项目生成代码。 我想创建一个GUI来自动编译解决方案,所以我不必加载Visual Studio只是为了触发重新编译。

我一直在寻找机会与Roslyn一起玩,并决定尝试使用Roslyn而不是msbuild来做到这一点。 不幸的是,我似乎找不到以这种方式使用Roslyn的任何好资源。

谁能指出我正确的方向?

您可以使用Roslyn.Services.Workspace.LoadSolution加载解决方案。 完成后,您需要按依赖顺序浏览每个项目,获取项目的Compilation并调用Emit

您可以使用下面的代码以依赖顺序获取编译。 (是的,我知道必须转发给IHaveWorkspaceServices很糟糕。在下一个公开发布中它会更好,我保证)。

 using Roslyn.Services; using Roslyn.Services.Host; using System; using System.Collections.Generic; using System.IO; class Program { static void Main(string[] args) { var solution = Solution.Create(SolutionId.CreateNewId()).AddCSharpProject("Foo", "Foo").Solution; var workspaceServices = (IHaveWorkspaceServices)solution; var projectDependencyService = workspaceServices.WorkspaceServices.GetService(); var assemblies = new List(); foreach (var projectId in projectDependencyService.GetDependencyGraph(solution).GetTopologicallySortedProjects()) { using (var stream = new MemoryStream()) { solution.GetProject(projectId).GetCompilation().Emit(stream); assemblies.Add(stream); } } } } 

注1: LoadSolution仍然使用LoadSolution msbuild来解析.csproj文件并确定文件/引用/编译器选项。

注意2:由于Roslyn尚未完成语言,因此当您尝试使用时,可能会有一些项目无法成功编译。

我还想动态编译完整的解决方案。 根据Kevin Pilch-Bisson的回答和Josh E的评论 ,我编写了代码来编译自己并将其写入文件。

使用的软件

Visual Studio社区2015 Update 1

Microsoft.CodeAnalysis v1.1.0.0(使用程序包管理器控制台Install-Package Microsoft.CodeAnalysis ,命令为Install-Package Microsoft.CodeAnalysis )。

 using System; using System.Collections.Generic; using System.IO; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Emit; using Microsoft.CodeAnalysis.MSBuild; namespace Roslyn.TryItOut { class Program { static void Main(string[] args) { string solutionUrl = "C:\\Dev\\Roslyn.TryItOut\\Roslyn.TryItOut.sln"; string outputDir = "C:\\Dev\\Roslyn.TryItOut\\output"; if (!Directory.Exists(outputDir)) { Directory.CreateDirectory(outputDir); } bool success = CompileSolution(solutionUrl, outputDir); if (success) { Console.WriteLine("Compilation completed successfully."); Console.WriteLine("Output directory:"); Console.WriteLine(outputDir); } else { Console.WriteLine("Compilation failed."); } Console.WriteLine("Press the any key to exit."); Console.ReadKey(); } private static bool CompileSolution(string solutionUrl, string outputDir) { bool success = true; MSBuildWorkspace workspace = MSBuildWorkspace.Create(); Solution solution = workspace.OpenSolutionAsync(solutionUrl).Result; ProjectDependencyGraph projectGraph = solution.GetProjectDependencyGraph(); Dictionary assemblies = new Dictionary(); foreach (ProjectId projectId in projectGraph.GetTopologicallySortedProjects()) { Compilation projectCompilation = solution.GetProject(projectId).GetCompilationAsync().Result; if (null != projectCompilation && !string.IsNullOrEmpty(projectCompilation.AssemblyName)) { using (var stream = new MemoryStream()) { EmitResult result = projectCompilation.Emit(stream); if (result.Success) { string fileName = string.Format("{0}.dll", projectCompilation.AssemblyName); using (FileStream file = File.Create(outputDir + '\\' + fileName)) { stream.Seek(0, SeekOrigin.Begin); stream.CopyTo(file); } } else { success = false; } } } else { success = false; } } return success; } } }