2010-11-01 19 views
7

Ich möchte alle Methoden auflisten, die von einer bestimmten Methode aufgerufen werden. Z.B. wenn ich folgenden Code habe:Wie ermittelt man, welche Methoden in einer Methode aufgerufen werden?

public void test1() { 

    test2(); 


    test3(); 
} 

Die Liste sollte test2() und test3() enthalten. Es wäre großartig, wenn Methoden der gleichen Klasse aber auch Methoden einer anderen Klasse aufgelistet werden könnten.

Additionaly würde Ich mag einen Weg finden, zu erkennen, welche Felder eines Verfahrens verwendet werden:

public class A { 

    private String test1 = ""; 
    private String test2 = ""; 

    public void test() { 
     Console.WriteLine(test1); 
    } 

} 

sollte daher Liste Test1.

Ich versuchte dies mit Mono.Cecil, aber leider konnte ich nicht viel Dokumentation über das Projekt finden. Weiß jemand, wie man das macht?

Edit: Ich möchte es mit Mono.Cecil tun, weil über seine API kann ich direkt die Ergebnisse in meiner Anwendung verwenden. Wenn ich integrierte Tools in Visual Studio oder ähnlichem verwende, ist es ziemlich schwierig, die Ergebnisse weiter zu verarbeiten.

Antwort

1

Dies kann nicht einfach mit der Reflektions-API in C# durchgeführt werden. Wirklich, Sie müssten den ursprünglichen Quellcode analysieren, was wahrscheinlich nicht die Art von Lösung ist, nach der Sie suchen. Aber zum Beispiel erhält Visual Studio diese Art von Informationen für das Refactoring.

Sie könnten irgendwo die IL analysieren - im Sinne von Reflector, aber das wäre ein riesiges Stück Arbeit, denke ich.

+0

Ja, ich habe es bereits mit der Reflection API versucht und es war nicht so einfach. Also habe ich versucht, Mono.Cecil zu verwenden, weil ich die Ergebnisse der Berechnung in meinem Code verwenden möchte. (siehe meine Bearbeitung) – RoflcoptrException

+0

Ah! Ich kenne Mono.Cecil nicht - aber es sieht sehr interessant aus. Wenn Sie bereit sind, sich mit der IL die Hände schmutzig zu machen, dann sollte das möglich sein - aber leider kann ich nicht helfen - viel Glück. –

1

können Sie .NET Reflector tool verwenden, wenn Sie zahlen möchten. Sie können auch einen Blick auf diese .NET Method Dependencies werfen, aber es wird schwierig, wie Sie in die IL gehen werden. Ein drittes möglich wäre, die Makro-Engine in VS zu verwenden, es hat eine Möglichkeit, Code zu analysieren, CodeElement, ich bin nicht sicher, ob es Abhängigkeiten tun kann.

+0

Ich möchte eine Farmework/Bibliothek verwenden, da ich die Ergebnisse der Berechnung direkt in meiner Anwendung verwenden möchte. (siehe meine Bearbeitung) – RoflcoptrException

+0

Edit: Ah ich sehe jetzt, das Reflektor-Tool hat auch eine API, das sieht ziemlich toll aus. Ich denke, es sollte in der Lage sein, zumindest einen Teil des Problems zu lösen. – RoflcoptrException

7

Ich habe nicht wirklich mit Cecil gearbeitet, aber die HowTo Seite zeigt, wie man die Typen aufzählt, scheint Ihr Problem nur Schleifen über die Anweisungen für diejenigen Ihr nach: Call and Load Field. Dieser Beispielcode scheint mit den Fällen zu tun zu haben, die Sie erwähnt haben, aber es könnte mehr sein, Sie sollten wahrscheinlich auch die anderen Call-Anweisungen überprüfen. Wenn Sie es rekursiv machen, vergewissern Sie sich, dass Sie die Methoden, die Sie bereits überprüft haben, im Auge behalten.

static void Main(string[] args) 
{ 
    var module = ModuleDefinition.ReadModule("CecilTest.exe"); 

    var type = module.Types.First(x => x.Name == "A"); 
    var method = type.Methods.First(x => x.Name == "test"); 

    PrintMethods(method); 
    PrintFields(method); 

    Console.ReadLine(); 
} 

public static void PrintMethods(MethodDefinition method) 
{ 
    Console.WriteLine(method.Name); 
    foreach (var instruction in method.Body.Instructions) 
    { 
     if (instruction.OpCode == OpCodes.Call) 
     { 
      MethodReference methodCall = instruction.Operand as MethodReference; 
      if(methodCall != null) 
       Console.WriteLine("\t" + methodCall.Name); 
     } 
    } 
} 


public static void PrintFields(MethodDefinition method) 
{ 
    Console.WriteLine(method.Name); 
    foreach (var instruction in method.Body.Instructions) 
    { 
     if (instruction.OpCode == OpCodes.Ldfld) 
     { 
      FieldReference field = instruction.Operand as FieldReference; 
      if (field != null) 
       Console.WriteLine("\t" + field.Name); 
     } 
    } 
} 
+0

Vielen Dank. Ich habe gestern schon einen ähnlichen Ansatz versucht, aber mein Problem ist, dass ModuleDefinition.ReadModule ("test.dll"); funktioniert nicht. Es gibt immer einen Fehler, dass ModuleDefinition die Methode ReadModule (String) – RoflcoptrException

+0

@ Roflcoptr nicht enthält, dann verwenden Sie einfach nicht die richtige Version von Cecil. Holen Sie es von http://github.com/jbevain/cecil und der Code, den Kris gepostet hat, funktioniert. –

+0

@Roflcoptr hast du das zur Arbeit gebracht? – Mario

Verwandte Themen