2013-08-06 6 views
17

Ich möchte alle rekursiven Aufrufe in meinem Code finden.Erkennen rekursiver Aufrufe in C# -Code

Wenn ich Datei in Visual Studio öffne, bekomme ich "Recursive call" -Symbol auf der linken Seite des Editors. enter image description here

Ich möchte die gesamte Lösung für solche Anrufe überprüfen.

Ich habe Resharper Command Line Tools und VS Add-In Resharper - Code Inspektion ohne Glück, diese Regel wird nicht in ihren Regelsatz angewendet.

Gibt es eine Möglichkeit, dass ich ganze Lösung inspizieren konnte - ich für diesen bläulichen „rekursive Aufruf“ Symbol :)

bearbeiten möchte wirklich nicht jede Datei öffnen und überprüfen: Ich bin Single interessiert -level Rekursion

+0

Sie sind sich bewusst, dass dieses Symbol nicht für mehrstufige Rekursion angezeigt wird? dh. Methode A ruft B an, welches wiederum A, etc. anruft? –

+0

Ja ich bin mir bewusst, ich möchte nur Single-Level-Rekursion. –

Antwort

16

Sie könnte tun Sie es mit Mono.Cecil.

Hier ist ein einfaches LINQPad Programm, das zeigt:

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"); 
} 

Dies wird ausgegeben, um die Methoden, die sich direkt aufruft. Beachten Sie, dass ich nur die Anweisung verarbeitet habe, ich bin mir nicht sicher, wie man die anderen Anrufanweisungen hier richtig behandelt, oder sogar wenn das sogar möglich ist.

Vorbehalt: Beachten Sie, dass dies, weil ich nur diesen einzelnen Befehl behandelt, nur mit statisch kompilierten Aufrufen funktioniert.

Virtuelle Anrufe, Anrufe über Schnittstellen, die zufällig auf die gleiche Methode zurückgehen, werden dadurch nicht erkannt, dafür ist viel fortgeschrittenerer Code erforderlich.

+2

Funktioniert wie ein Charme, danke –

+1

Nur um zu klären, falls jemand nicht sicher ist; Sie brauchen Mono nicht, um dies zu tun. In LinqPad Pro können Sie das NuGet-Paket 'Install-Package Mono.Cecil' im Fenster Abfrageeigenschaften hinzufügen. Wenn Sie ein billiger Skate sind und die kostenlose Version haben, dann müssen Sie das nugget-Paket in ein anderes temporäres Projekt herunterladen und dann zusätzliche Assemblys zu Ihrer Abfrage hinzufügen, indem Sie die Abfrageeigenschaften verwenden. Andernfalls ModuleDefinition.ReadModule wird nicht die richtigen Referenzen zu arbeiten. – Junto

+0

Ich habe heruntergeladen https://github.com/jbevain/cecil/releases Build und führen Sie mit dem obigen Code und liste mich alle rekursiv aufrufen. Vielen Dank! – Zyo