How to get il of one method body with roslyn?

前端 未结 1 1576
别那么骄傲
别那么骄傲 2020-12-31 22:59

I want to get il of one method in my c# source code file.I have opened solution with roslyn and find the method symbol like below

Roslyn.Compilers.Common.         


        
相关标签:
1条回答
  • 2020-12-31 23:29

    Unfortunately, the IL generation is entirely hidden inside the Emit call in Roslyn. But I'll give a simple to get you started.

    Let's suppose you start of with an existing compilation:

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

    where method is your ISymbol. Then you can do following:

    // 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 a more complex case, you'd probably need to emit the entire/initial compilation, and get the generated method via reflection.

    Refer to this post to find out what you can do with the results of GetMethodBody().

    0 讨论(0)
提交回复
热议问题