Sfortunatamente, la generazione IL è completamente nascosta all'interno della chiamata Emit
in Roslyn. Ma ti darò una semplice idea per iniziare.
Supponiamo che si avvia di con una compilation esistente:
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();
dove method
è il vostro ISymbol
. Poi si può fare seguente:
// 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 un caso più complesso, si sarebbe probabilmente bisogno di emettere l'intero/iniziale di compilazione, e di ottenere il metodo generato attraverso la riflessione.
Fare riferimento a this post per scoprire cosa è possibile fare con i risultati di GetMethodBody()
.
Compilare il codice, ottenere il corpo. Non è come se Roslyn potesse semplicemente compilare un metodo in un unico file sorgente senza contesto :) – Luaan
Perché hai bisogno dell'IL? Cosa vuoi fare con esso? – svick