7
votes

Comment déterminer quelles méthodes sont appelées dans une méthode?

J'aimerais énumérer toutes les méthodes appelées à partir d'une méthode spécifique. Par exemple. Si j'ai le code suivant:

public class A {

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

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

}


0 commentaires

3 Réponses :


1
votes

Cela ne peut pas être fait simplement à l'aide de l'API de réflexion dans C #. Vraiment, vous auriez besoin d'analyser le code source d'origine qui n'est probablement pas le genre de solution que vous recherchez. Mais par exemple, voici comment Visual Studio obtient ce type d'informations à refactoriser.

Vous pourriez vous rendre quelque part en analysant l'IL - le long des lignes de quel réflecteur ne fait que ce serait un énorme morceau de travail que je pense.


2 commentaires

Oui, je l'ai déjà essayé avec l'API de réflexion et ce n'était pas si facile. J'ai donc essayé d'utiliser mono.cecil car j'aimerais utiliser les résultats du calcul de mon code. (Voir mon édition)


Ah! Je ne connais pas mono.cecil - mais ça a l'air très intéressant. Si vous êtes prêt à faire sale les mains avec l'IL, cela devrait être possible - mais désolé je ne peux pas vous aider - bonne chance.



1
votes

Vous pouvez utiliser outil de réflecteur .NET si vous voulez payer . Vous pouvez également jeter un coup d'oeil à ce Dépendances de méthode .NET devient difficile cependant, comme vous allez aller dans l'IL. Un troisième possible serait d'utiliser le moteur macro dans VS, il dispose d'une installation pour analyser le code, codeelement , je ne sais pas si cela peut faire des dépendances.


2 commentaires

J'aimerais utiliser une farcework / bibliothèque, car j'aimerais utiliser les résultats du calcul directement dans ma demande. (Voir mon édition)


EDIT: AH Je vois maintenant, l'outil de réflecteur a également une API, cela a l'air plutôt génial. Je pense que cela devrait être capable de résoudre au moins une partie du problème.



9
votes

Je n'ai pas vraiment travaillé avec Cecil, mais le HOWTO page indique comment énumérer les types, votre problème Seulement semble avoir besoin de boucler sur les instructions pour ceux après: appel et champ de chargement. Ce code d'exemple semble gérer les cas que vous avez mentionnés, mais il peut probablement y avoir davantage, vous devriez probablement vérifier également les autres instructions d'appel. Si vous le faites récursif, assurez-vous de garder une trace des méthodes que vous avez déjà vérifiées.

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


3 commentaires

Merci beaucoup. J'ai déjà essayé une approche similaire hier, mais mon problème est que Modulédechinition.readmodule ("test.dll"); ne fonctionne pas. Il y a une erreur d'erreur que la modulation ne contient pas la méthode readmodule (chaîne)


@Roflcoptr Alors vous n'utilisez simplement pas la version appropriée de Cecil. Obtenez-le de Github.com/jbevain/cecil et le code KRIS posté fonctionnera.


@Mario: Je pense que oui, mais aujourd'hui et demain, je n'ai pas le temps de vérifier cet ancien projet ...