Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get il of one method body with roslyn?

Tags:

c#

roslyn

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.ISymbol s=GetMethodSymbolAtPosition (30);

I have an ISymbol how get il now?

like image 860
mohsen Avatar asked Mar 02 '16 07:03

mohsen


1 Answers

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

like image 54
m0sa Avatar answered Oct 03 '22 19:10

m0sa