2012-11-07 14 views
19

मेरे पास सॉफ़्टवेयर का एक टुकड़ा है जो उपयोगकर्ता क्रियाओं के आधार पर सी # प्रोजेक्ट के लिए कोड उत्पन्न करता है। मैं समाधान को स्वचालित रूप से संकलित करने के लिए एक जीयूआई बनाना चाहता हूं, इसलिए मुझे रीकंपाइल ट्रिगर करने के लिए केवल विजुअल स्टूडियो को लोड करने की आवश्यकता नहीं है।मैं Roslyn के साथ एक सी # समाधान कैसे संकलित करूं?

मैं रोज़लिन के साथ खेलने का मौका ढूंढ रहा हूं और ऐसा करने के लिए msbuild के बजाय Roslyn का उपयोग करने और उपयोग करने का निर्णय लिया है। दुर्भाग्यवश, मुझे इस फैशन में रोज़लिन का उपयोग करने पर कोई अच्छा संसाधन नहीं दिख रहा है।

क्या कोई मुझे सही दिशा में इंगित कर सकता है?

उत्तर

22

आप 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<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); 
      } 
     } 
    } 
} 

Note1: LoadSolution अभी भी कवर .csproj फ़ाइलों को पार्स और फ़ाइलों/संदर्भ/संकलक विकल्पों का निर्धारण करने के लिए के तहत उपयोग MSBuild करता है।

नोट 2: जैसा कि रोज़लिन अभी तक भाषा पूरी नहीं है, वहां ऐसी परियोजनाएं होंगी जो आप प्रयास करते समय सफलतापूर्वक संकलित नहीं करते हैं।

+0

वहाँ निर्भरता आदेश ('sln.ProjectsInDependencyOrder' की तरह) का निर्धारण करने का एक सुविधाजनक तरीका है या मैं अपने दम पर लागू करने के लिए होगा यह कुछ है? (उदाहरण के लिए प्रोजेक्ट-रेफरेंस के माध्यम से जाना और एक निर्भरता पेड़ बनाना) – NobodysNightmare

+1

एक आईप्रोजेक्ट निर्भरता सेवा है जिसमें GetTopologicallySortedProjects() है। मेरे पास कंप्यूटर को आसानी से जांचने के लिए आसान नहीं है, लेकिन इसे बाद में अपडेट किया जाएगा। –

+0

कुछ कोड जोड़ने के लिए उत्तर संपादित किया गया। –

8

मैं भी फ्लाई पर एक पूर्ण समाधान संकलित करना चाहता था। Kevin Pilch-Bisson's answer और Josh E's comment से बिल्डिंग, मैंने स्वयं को संकलित करने और फ़ाइलों को लिखने के लिए कोड लिखा था।

सॉफ्टवेयर का इस्तेमाल किया

दृश्य स्टूडियो समुदाय 2015 अपडेट 1

Microsoft.CodeAnalysis v1.1.0.0 (आदेश 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<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 के लिए कोई मूल्य नहीं मिला। System.Object युक्त कोई असेंबली नहीं मिली थी और न ही विकल्प के माध्यम से निर्दिष्ट RuntimeMetadataVersion के लिए एक मान था। – Aflred

+0

FYI इस उदाहरण का उपयोग करने के लिए आपको Microsoft.build.Tasks.Core और Microsoft.build Packages –

+0

इंस्टॉल करने की भी आवश्यकता होगी यह roslyn.services नामस्थान अप्रचलित है क्योंकि यह एक बेहतर उत्तर प्रतीत होता है। –

संबंधित मुद्दे