2016-03-02 61 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

相关问题