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.
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? –
Ja ich bin mir bewusst, ich möchte nur Single-Level-Rekursion. –