Posso usare la riflessione per ispezionare il codice in un metodo?

Sto giocando con l’API di riflessione C #. Posso facilmente caricare informazioni sul Type di classi, metodi ecc. In un assembly, tuttavia ora mi chiedo come posso caricare e leggere il codice all’interno di un metodo?

Risposta di base:

Non puoi con l’API reflection (System.Reflection).

Il motivo è che la reflection api è progettata per funzionare sui metadati (tipo di classi, nome e firma dei metodi, …) ma non sul livello dei dati (che sarebbe il stream IL stesso).

Risposta estesa:

È ansible emettere (ma non leggere) IL con System.Reflection.Emit (ad es. Classe ILGenerator).

Tramite MethodInfo.GetMethodBody() è ansible ottenere il stream IL binario per l’implementazione di un metodo. Ma questo di solito è completamente inutile da solo.

Ci sono librerie esterne (come Cecil ) che puoi usare per leggere / modificare / aggiungere / eliminare il codice all’interno di un metodo.

Dipende da cosa intendi leggendo il codice. Ci sono 4 forms del codice.

1- Il codice sorgente es. il C # originale o VB.NET – No, non è ansible ottenere questo con la riflessione
2- Il codice IL simbolico – No, non puoi ottenerlo con la riflessione
3- Il codice assembly JITed – No, non è ansible ottenere questo con la riflessione

4- I byte IL, i byte effettivi a cui viene compilato IL, questo è ansible ottenere.

Date un’occhiata a MethodBase.GetMethodBody () per esempio, potete ottenere i byte IL, le variabili locali, i frame delle eccezioni ecc. http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getmethodbody aspx

Ora ci sono librerie / pacchetti che ti permettono di ispezionare il codice del metodo e persino decompilarlo in Expression :

È una specie di lattina. La funzione rilevante è MethodBase.GetMethodBody .

Non è esattamente l’API più utile. È ansible ottenere alcune informazioni di base su cosa c’è dentro il metodo e ottenere l’IL come array di byte. Questo è tutto.

C’è un’API leggermente migliore nella libreria Mono.Cecil , che espone una class MethodDefinition con la propria implementazione MethodBody che contiene Instructions reali, quindi non è necessario interpretare il codice byte grezzo. Tuttavia, se stai cercando di ottenere il codice C # da questo alla Reflector, sarai molto deluso. Inoltre, Cecil non è molto ben documentato.

Se vuoi ancora provare, allora buona fortuna.

Se non hai bisogno di farlo in tempo reale, dai un’occhiata a Reflector . È ansible disassemblare qualsiasi assembly .NET (incluse le DLL MS core) e vedere il codice nella lingua scelta. Questo può essere molto educativo.

Aggiornamento Qualcuno ha provato a usare Reflector su Reflector per capire come è fatto?

No
Questa è una funzionalità prevista per la prossima versione di C #. Puoi usare CodeDom per ottenere più informazioni del riflesso, ma non puoi ancora interrogare l’albero di analisi.

Bene c’è sempre mono, in mono il compilatore è un servizio, e potresti ottenere gli alberi di analisi in fase di esecuzione.

La domanda migliore è perché vuoi?

Sì, ci deve essere un modo per raggiungere questo objective: lo strumento .NET Reflector fa anche questo. Non posso dirti come è fatto lì, però.