2009-05-12 8 views
16

Heres mon problème:C# Réflexion: Obtenir * tous * les assemblages actifs dans une solution?

J'ai 2 projets - un des projets « communs » avec des actes comme une bibliothèque avec tous les types de code de soutien, et le programme réel qui utilise ladite projet dans plusieurs de ses appels. Nous appellerons ces projets "commun" et "programme". Ils sont tous les deux dans la même solution.

Dans "Common", j'ai une classe pour les tâches de réflexion commune, comme la création d'une instance. Si j'appelle GetExecutingAssembly, il obtient tous les types "Common", mais quand j'utilise GetEntryAssembly, j'obtiens les types "Program".

Bien que je puisse certainement éditer le code pour travailler avec 2 ensembles d'asm, j'ai peur d'une situation où il y a plus que 2 projets dans la solution - disons 5 (ne sais pas pourquoi, mais laisse allez-y pour l'instant), et j'ai peur que l'appel de GetExecutingAssembly et de GetEntryAssembly n'obtienne pas tous les types dans le programme entier.

Y at-il quelque chose d'autre que je peux faire pour obtenir tous les types dans une solution ?

Répondre

49
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies(); 

Ceci obtiendra tous les assemblys chargés dans l'AppDomain actuel. Comme indiqué dans les commentaires, il est possible de générer plusieurs AppDomains, auquel cas chacun peut avoir ses propres assemblys. L'avantage immédiat de cette opération est que vous pouvez décharger les assemblys en déchargeant le domaine AppDomain contenant.

+3

mai ou peut ne pas soumis à 1) si l'application génère plusieurs AppDomains 2) si tous Les assemblages ref ont été chargés avant ce point – Gishu

+1

Parfait, merci! – cyberconte

+0

@Gishu: "si tous les assemblys ref ont été chargés avant ce point" Vous ne savez pas exactement ce que vous entendez par là. Peux-tu élaborer? – bsneeze

7

Que diriez-vous de GetReferencedAssemblies pour travailler sur les entrées de métadonnées AssemblyRef? La «solution» n'est pas quelque chose que le CLR sait ou se soucie de .. il traite dans les assemblées.

private static List<Assembly> GetListOfEntryAssemblyWithReferences() 
{ 
    List<Assembly> listOfAssemblies = new List<Assembly>(); 
    var mainAsm = Assembly.GetEntryAssembly(); 
    listOfAssemblies.Add(mainAsm); 

    foreach (var refAsmName in mainAsm.GetReferencedAssemblies()) 
    { 
    listOfAssemblies.Add(Assembly.Load(refAsmName)); 
    } 
    return listOfAssemblies; 
} 

:
Avertissements 1. Vous avez encore besoin de filtrer les ensembles de base * Système 2. Cela va juste un niveau de profondeur dans la chaîne ref .. mais peut être fait récursive - avec plus de code..

5

En outre: Certains assemblys ne sont pas chargés immédiatement, vous devez donc également placer un gestionnaire d'événements dans l'événement de chargement d'assembly de l'AppDomain.

AppDomain.CurrentDomain.AssemblyLoad += .... 
29

Ceci est un vraiment vieille question, mais pour référence future est ici une mise en œuvre complète:

public static IEnumerable<Assembly> GetAssemblies() 
    { 
     var list = new List<string>(); 
     var stack = new Stack<Assembly>(); 

     stack.Push(Assembly.GetEntryAssembly()); 

     do 
     { 
      var asm = stack.Pop(); 

      yield return asm; 

      foreach (var reference in asm.GetReferencedAssemblies()) 
       if (!list.Contains(reference.FullName)) 
       { 
        stack.Push(Assembly.Load(reference)); 
        list.Add(reference.FullName); 
       } 

     } 
     while (stack.Count > 0); 

    } 
+0

Joli, merci pour le partage - juste ce dont j'avais besoin. – Dav

+0

@Dav vous êtes les bienvenus! –

+0

Essayez d'utiliser hashset insteas d'une liste. – AgentFire

Questions connexes