2013-08-06 10 views
17

Desidero trovare tutte le chiamate ricorsive nel mio codice.Rileva chiamate ricorsive nel codice C#

Se apro il file in Visual Studio, viene visualizzata l'icona "Chiamata ricorsiva" sul lato sinistro di Editor. enter image description here

Voglio ispezionare l'intera soluzione per tali chiamate.

Ho usato gli strumenti di riga di comando di Resharper e il sottotitolo aggiuntivo di VS - Ispezione codice senza fortuna, questa regola non è applicata nel loro set di regole.

Esiste un modo che ho potuto ispezionare intera soluzione - davvero non voglio aprire ogni file e verificare la presenza di che il blu-ish icona "chiamata ricorsiva" :)

Edit: Sono interessato a singolo -velocità di ricorsione

+0

Sei consapevole che questa icona non viene visualizzata per la ricorsione a più livelli? vale a dire. metodo A chiama B che a sua volta chiama A, ecc.? –

+0

Sì, lo so, voglio solo una ricorsione a livello singolo. –

risposta

16

È possibile farlo con Mono.Cecil.

Ecco un semplice programma di LINQPad che dimostra:

const string AssemblyFilePath = @"path\to\assembly.dll"; 

void Main() 
{ 
    var assembly = ModuleDefinition.ReadModule(AssemblyFilePath); 
    var calls = 
     (from type in assembly.Types 
     from caller in type.Methods 
     where caller != null && caller.Body != null 
     from instruction in caller.Body.Instructions 
     where instruction.OpCode == OpCodes.Call 
     let callee = instruction.Operand as MethodReference 
     select new { type, caller, callee }).Distinct(); 

    var directRecursiveCalls = 
     from call in calls 
     where call.callee == call.caller 
     select call.caller; 

    foreach (var method in directRecursiveCalls) 
     Debug.WriteLine(method.DeclaringType.Namespace + "." + method.DeclaringType.Name + "." + method.Name + " calls itself"); 
} 

Questa uscita volontà i metodi che si chiamate direttamente. Si noti che ho elaborato solo l'istruzione Call, non sono sicuro di come gestire correttamente le altre istruzioni di chiamata qui, o anche se è possibile.

Caveat: Si noti che questo, poiché ho gestito solo questa singola istruzione, funziona solo con chiamate compilate staticamente.

Le chiamate virtuali, le chiamate attraverso le interfacce, che capita di tornare allo stesso metodo, non verranno rilevate da questo, per questo è necessario un codice molto più avanzato.

+2

Funziona come un fascino, grazie –

+1

Giusto per chiarire, nel caso qualcuno non sia sicuro; non hai bisogno di Mono per farlo. In LinqPad Pro è possibile aggiungere il pacchetto NuGet 'Installa-Pacchetto Mono.Cecil' nella finestra Proprietà della query. Se sei uno skate economico e disponi della versione gratuita, devi scaricare il pacchetto nuget in un altro progetto temporaneo, quindi aggiungere ulteriori assembly alla query utilizzando Proprietà query. Altrimenti ModuleDefinition.ReadModule non avrà i riferimenti corretti per funzionare. – Junto

+0

Ho scaricato https://github.com/jbevain/cecil/releases ed è stato creato ed eseguito con il codice sopra e mi elenca tutte le chiamate ricorsive. Grazie! – Zyo