2012-11-07 12 views
19

Kullanıcı eylemlerine dayalı bir C# projesi için kod üreten bir yazılım parçam var. Çözümü otomatik olarak derlemek için bir GUI oluşturmak istiyorum, böylece bir derlemeyi tetiklemek için Visual Studio'yu yüklemek zorunda kalmam.C# çözümünü Roslyn ile nasıl derlerim?

Roslyn ile biraz oyun oynama şansı buldum ve bunu yapmak için msbuild yerine Roslyn kullanmayı denedim. Ne yazık ki, bu moda Roslyn'i kullanmanın iyi bir kaynağını bulamıyorum.

Beni doğru yöne yönlendiren var mı?

cevap

22

Çözümü Roslyn.Services.Workspace.LoadSolution kullanarak yükleyebilirsiniz. Bunu yaptıktan sonra, her bir projeye bağımlılık sırasına girmeniz, proje için Compilation numarasını almanız ve üzerinde Emit numarasını aramanız gerekir.

Derlemeleri bağımlılık sırasına göre aşağıdaki gibi bir kodla alabilirsiniz. (Evet, IHaveWorkspaceServices'ın yayınlanması gerekeceğini biliyorum. Bir sonraki kamu yayınında daha iyi olacak, söz veriyorum).

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<IProjectDependencyService>(); 
     var assemblies = new List<Stream>(); 
     foreach (var projectId in projectDependencyService.GetDependencyGraph(solution).GetTopologicallySortedProjects()) 
     { 
      using (var stream = new MemoryStream()) 
      { 
       solution.GetProject(projectId).GetCompilation().Emit(stream); 
       assemblies.Add(stream); 
      } 
     } 
    } 
} 

Not 1: LoadSolution hala .Csproj dosyalarını ayrıştırmak ve dosya/referanslar/derleyici seçeneklerini belirlemek için yorganın altında kullanılması msbuild yapar.

Not2: Roslyn henüz dil tamamlanmadığı için, bunu denediğinizde başarıyla derleme olmayan projeler olacaktır.

+0

(sln.ProjectsInDependencyOrder' 'gibi) bağımlılık sırasının belirlenmesi uygun bir yolu var mı yoksa başıma uygulamak zorunda kalacak bu bir şeydir? (ör. Proje başvurularından geçme ve bağımlılık ağacı oluşturma) – NobodysNightmare

+1

GetTopologicallySortedProjects() içeren bir IProjectDependencyService vardır. Tam olarak nasıl alınacağını kontrol etmek için kullanışlı bir bilgisayarım yok, ancak daha sonra güncellenir. –

+0

Bazı kod eklemek için cevabı düzenleyin. –

8

Ayrıca, tam bir çözümü anında derlemek istedim. Kevin Pilch-Bisson's answer ve Josh E's comment'dan yola çıkarak, kendisini derlemek ve dosyalara yazmak için kod yazdım.

Yazılım Kullanılan

Visual Studio Topluluk 2015 Güncelleme 1

Microsoft.CodeAnalysis v1.1.0.0 (komutuyla Install-Package Microsoft.CodeAnalysis ile Paket Yöneticisi Konsolu kullanılarak Yüklü).

Kod

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<string, Stream> assemblies = new Dictionary<string, Stream>(); 

      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; 
     } 
    } 
} 
+0

RuntimeMetadataVersion için değer bulunamadı. System.Object içeren hiçbir derleme bulunamadı ve seçenekler aracılığıyla belirtilen RuntimeMetadataVersion değeri yok. – Aflred

+0

FYI bu örneği kullanmak için Microsoft.Build.Tasks.Core ve Microsoft.Build Paketlerini yüklemeniz gerekir –

+0

Bu roslyn.services ad alanı eskimiş gibi çok daha iyi bir yanıt gibi görünüyor. –