2010-11-01 10 views
7

Me gustaría enumerar todos los métodos que se invocan desde un método específico. P.ej. si tengo el siguiente código:¿Cómo determinar qué métodos se llaman en un método?

public void test1() { 

    test2(); 


    test3(); 
} 

La lista debe contener test2() y test3(). Sería fantástico si se pudieran enumerar los métodos de la misma clase pero también los métodos de otra clase.

Adicionalmente Me gustaría encontrar una manera de detectar los campos que se utiliza un método de:

public class A { 

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

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

} 

, por lo tanto, deben figurar los test1.

Intenté esto usando Mono.Cecil, pero desafortunadamente no pude encontrar mucha documentación sobre el proyecto. Entonces, ¿alguien sabe cómo hacer eso?

Editar: Me gustaría hacerlo con Mono.Cecil porque sobre su API puedo usar directamente los resultados en mi aplicación. Si utilizo herramientas integradas en Visual Studio o similares, es bastante difícil procesar los resultados.

Respuesta

1

Esto no se puede hacer simplemente usando la API de reflexión dentro de C#. Realmente necesitarías analizar el código fuente original que probablemente no sea el tipo de solución que estás buscando. Pero, por ejemplo, así es como Visual Studio obtiene este tipo de información para hacer refactorizaciones.

Puede que llegue a algún lado analizando la IL, en la línea de lo que hace Reflector, pero creo que sería una gran obra.

+0

Sí, ya lo intenté con la API de reflexión y no fue tan fácil. Así que traté de usar Mono.Cecil porque me gustaría usar los resultados del cálculo en mi código. (ver mi edición) – RoflcoptrException

+0

¡Ah! No estoy familiarizado con Mono.Cecil, pero parece muy interesante. Si estás preparado para ensuciarte las manos con el IL, entonces esto debería ser posible, pero lo siento, no puedo ayudarte, buena suerte. –

1

puede usar .NET Reflector tool si desea pagar. También puedes echarle un vistazo a este .NET Method Dependencies, pero se vuelve complicado, ya que vas a ir a la IL. Una tercera posible sería usar el motor de macros en VS, tiene una facilidad para analizar código, CodeElement, aunque no estoy seguro si puede hacer dependencias.

+0

Me gustaría usar un farmework/library, ya que me gustaría utilizar los resultados del cálculo directamente en mi aplicación. (ver mi edición) – RoflcoptrException

+0

Editar: Ah, ahora veo, la herramienta Reflector también tiene una API, esto se ve bastante impresionante. Creo que debería ser capaz de resolver al menos parte del problema. – RoflcoptrException

7

No he trabajado realmente con Cecil, pero la página HowTo muestra cómo enumerar los tipos, su problema solo parece requerir que se repitan las instrucciones para las siguientes: Llamar y cargar campo. Este código de muestra parece manejar los casos que mencionó, pero puede haber más, probablemente también debería consultar las otras instrucciones de la llamada. Si lo hace recursivo, asegúrese de realizar un seguimiento de los métodos que ya ha verificado.

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

Muchas gracias. Ya intenté un enfoque similar ayer, pero mi problema es ese ModuleDefinition.ReadModule ("test.dll"); no funciona Siempre hay un error que ModuleDefinition no contiene el método ReadModule (String) – RoflcoptrException

+0

@Roflcoptr, entonces simplemente no está usando la versión correcta de Cecil. Obtenlo de http://github.com/jbevain/cecil y el código que Kris publique funcionará. –

+0

@Roflcoptr ¿conseguiste que esto funcionara? – Mario

Cuestiones relacionadas