2016-03-02 11 views
5

voglio ottenere il di un metodo nel mio c file.I # codice sorgente hanno aperto soluzione Roslyn e trovare il simbolo metodo come di seguitoCome ottenere il corpo di un metodo con roslyn?

Roslyn.Compilers.Common.ISymbol s=GetMethodSymbolAtPosition (30); 

ho un ISymbol come ottenere il momento?

+0

Compilare il codice, ottenere il corpo. Non è come se Roslyn potesse semplicemente compilare un metodo in un unico file sorgente senza contesto :) – Luaan

+0

Perché hai bisogno dell'IL? Cosa vuoi fare con esso? – svick

risposta

7

Sfortunatamente, la generazione IL è completamente nascosta all'interno della chiamata Emit in Roslyn. Ma ti darò una semplice idea per iniziare.

Supponiamo che si avvia di con una compilation esistente:

var initial = CSharpCompilation.Create("Existing") 
    .AddReferences(MetadataReference.CreateFromFile(typeof(object).Assembly.Location)) 
    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(@"  
     namespace Test 
     { 
      public class Program 
      { 
       public static void HelloWorld() 
       { 
        System.Console.WriteLine(""Hello World""); 
       } 
      } 
     }"));  
var method = initial.GetSymbolsWithName(x => x == "HelloWorld").Single(); 

dove method è il vostro ISymbol. Poi si può fare seguente:

// 1. get source 
var methodRef = method.DeclaringSyntaxReferences.Single(); 
var methodSource = methodRef.SyntaxTree.GetText().GetSubText(methodRef.Span).ToString(); 

// 2. compile in-memory as script 
var compilation = CSharpCompilation.CreateScriptCompilation("Temp") 
    .AddReferences(initial.References) 
    .AddSyntaxTrees(SyntaxFactory.ParseSyntaxTree(methodSource, CSharpParseOptions.Default.WithKind(SourceCodeKind.Script))); 

using (var dll = new MemoryStream()) 
using (var pdb = new MemoryStream()) 
{ 
    compilation.Emit(dll, pdb); 

    // 3. load compiled assembly 
    var assembly = Assembly.Load(dll.ToArray(), pdb.ToArray()); 
    var methodBase = assembly.GetType("Script").GetMethod(method.Name, new Type[0]); 

    // 4. get il or even execute 
    var il = methodBase.GetMethodBody(); 
    methodBase.Invoke(null, null); 
} 

In un caso più complesso, si sarebbe probabilmente bisogno di emettere l'intero/iniziale di compilazione, e di ottenere il metodo generato attraverso la riflessione.

Fare riferimento a this post per scoprire cosa è possibile fare con i risultati di GetMethodBody().

+0

"Sfortunatamente, la generazione di IL è completamente nascosta all'interno della chiamata Emit di Roslyn." Ti capita di sapere dove a Roslyn viene generato IL? (Roslyn è un programma enorme - ho appena iniziato a guardarlo - e mi piacerebbe provare a modificare l'IL generato per alcune affermazioni in C#). – RenniePet

Problemi correlati