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