2016-03-02 32 views
5

我想一個方法的IL在我的C#源代碼file.I已經打開的解決方案與羅斯林,發現像下面如何用roslyn獲得一個方法體的il?

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

我有一個ISymbol現在怎麼得到金正日的方法符號?

+0

編譯代碼,獲取正文。這不是像羅斯林可以在沒有上下文的情況下在一個源文件中編譯一種方法:) – Luaan

+0

爲什麼你需要IL?你想用它做什麼? – svick

回答

7

不幸的是,IL代完全隱藏在Roslyn的Emit調用中。但我會給你一個簡單的開始。

讓我們假設你有一個現有的編輯開始的:

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(); 

其中method是你ISymbol。然後,你可以做到以下幾點:

// 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); 
} 

在更復雜的情況下,你可能需要發出整個/初始編譯,並通過反射得到生成的方法。

請參閱this post以瞭解可以對GetMethodBody()的結果執行哪些操作。

+0

「不幸的是,IL一代完全隱藏在Roslyn的Emit呼叫中。」你碰巧知道IL中Roslyn在哪裏產生? (Roslyn是一個巨大的程序 - 我剛開始着眼於它 - 我想嘗試調整爲某些C#語句生成的IL。) – RenniePet

相關問題