2010-01-14 17 views
3

J'essaie de trouver tous les types dont dépend un type donné, y compris les interfaces, les classes abstraites, les énumérations, les structures, etc. Je veux charger un assemblage, et imprimer une liste de tous les types définis dedans et leurs dépendances. Jusqu'à présent, j'ai pu trouver tous les types externes d'un ensemble CLR dépend de l'utilisation Mono.Cecil, par exemple.Comment puis-je trouver toutes les dépendances de type d'un type donné dans un assemblage de langage basé sur CLR?

using System; 
using Mono.Cecil; 
using System.IO; 

FileInfo f = new FileInfo("SomeAssembly.dll"); 
AssemblyDefinition assemDef = AssemblyFactory.GetAssembly (f.FullName); 
List<TypeReference> trList = new List<TypeReference>(); 

foreach(TypeReference tr in assemblyDef.MainModule.TypeReferences){ 
    trList.Add(tr.FullName); 
} 

Cette liste peut également être obtenue en utilisant le disasembler mono, par exemple "monodis SomeAssembly.dll --typeref", mais cette liste ne marche pas semblent inclure des primitives, par exemple System.Void, System.Int32, etc

Je dois traiter chaque type individuellement, et obtenir tous les types dont un type donné dépend, même si les types sont définis dans le même assemblage. Est-il possible de faire cela en utilisant Mono.Cecil ou un autre projet? Je sais que cela peut être fait en chargeant l'ensemble, puis en itérant sur chaque type défini, puis en chargeant l'IL du type et en le scannant pour des références, mais je suis sûr qu'il y a un meilleur moyen. Idéalement, il fonctionnera également avec des classes internes anonymes.

Cela devrait également fonctionner si plusieurs modules sont définis dans le même assemblage.

Répondre

1

AJ, je eu le même problème où je devais traverser les types dans un ensemble et je me suis installé sur l'utilisation Mono.Cecil. La façon dont j'étais capable de parcourir chaque classe et si une propriété dans une classe n'était pas une autre classe au lieu d'un type CLR était par une fonction récursive.

private void BuildTree(ModuleDefinition tempModuleDef , TypeDefinition tempTypeDef, TreeNode rootNode = null) 
    { 
      AssemblyTypeList.Add(tempTypeDef); 

      TreeNode tvTop = new TreeNode(tempTypeDef.Name); 

      // list all properties 
      foreach (PropertyDefinition tempPropertyDef in tempTypeDef.Properties) 
      { 
       //Check if the Property Type is actually a POCO in the same Assembly 
       if (tempModuleDef.Types.Any(q => q.FullName == tempPropertyDef.PropertyType.FullName)) 
       { 
        TypeDefinition theType = tempModuleDef.Types.Where(q => q.FullName == tempPropertyDef.PropertyType.FullName) 
                   .FirstOrDefault(); 
        //Recursive Call 
        BuildTree(tempModuleDef, theType, tvTop); 

       } 

       TreeNode tvProperty = new TreeNode(tempPropertyDef.Name); 
       tvTop.Nodes.Add(tvProperty); 
      } 

      if (rootNode == null) 
       tvObjects.Nodes.Add(tvTop); 
      else 
       rootNode.Nodes.Add(tvTop); 

    } 

Cette fonction est appelée par ma fonction principale dont l'essentiel est

 public void Main() 
     { 
     AssemblyDefinition assemblyDef = AssemblyDefinition.ReadAssembly(dllname); 

     //Populate Tree 
     foreach (ModuleDefinition tempModuleDef in assemblyDef.Modules) 
     { 
      foreach (TypeDefinition tempTypeDef in tempModuleDef.Types) 
      { 
       BuildTree(tempModuleDef ,tempTypeDef, null); 
      } 
     } 

     } 
1

Jetez un coup d'œil à NDepend - il le fait, et bien plus encore.

-Oisin

+0

Merci Oisin, je sais NDepend, il est un excellent produit. J'essaie de générer une liste de types dépendants afin que je puisse l'utiliser dans un autre outil. NDepend n'est donc pas l'outil dont j'ai besoin. –