2009-05-12 19 views
16

Ecco il mio problema:C# Reflection: ottieni * tutti * gli assembly attivi in ​​una soluzione?

Ho 2 progetti - un progetto "comune" con atti come una libreria con tutti i tipi di codice di supporto e il programma effettivo che utilizza detto progetto in molte delle sue chiamate. Chiameremo questi progetti "Comune" e "Programma". Sono entrambi nella stessa soluzione.

All'interno di "Comune", ho una classe per le attività di riflessione di Commo, come la creazione di un'istanza. Se chiamo GetExecutingAssembly, ottiene tutti i tipi "comuni", tuttavia quando uso GetEntryAssembly ottengo i tipi di "Programma".

Mentre io sicuramente posso modificare il codice per lavorare con 2 set di asm, ho paura di una situazione in cui ci sono più di 2 progetti nella soluzione - diciamo 5 (non so perché, ma lasciamo andiamo lì per ora), e temo che chiamare GetExecutingAssembly e GetEntryAssembly non ottenga tutti i Tipi nell'intero programma.

C'è qualcos'altro che posso fare per ottenere tutti i tipi in una soluzione ?

risposta

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

Otterrà tutti gli assembly caricati nell'AppDomain corrente.

Come indicato nei commenti, è possibile generare più AppDomain, nel qual caso ognuno può avere i propri assembly. Il vantaggio immediato consiste nel fatto che è possibile scaricare gli assembly scaricando l'AppDomain che lo contiene.

+3

può o non può funzionare soggetto a 1) se l'applicazione genera più AppDomain 2) Se tutto ref assembly sono stati caricati prima di questo punto – Gishu

+1

Perfetto, grazie! – cyberconte

+0

@Gishu: "se tutti i gruppi di riferimento sono stati caricati prima di questo punto" Non sei proprio sicuro di cosa intendi con questo. Puoi elaborare? – bsneeze

7

Che ne dici di GetReferencedAssemblies per risolvere le voci dei metadati AssemblyRef? La 'soluzione' non è qualcosa di cui il CLR sa o di cui preoccuparsi .. tratta in Assemblee.

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

Avvertenze:
1. Hai ancora bisogno di filtrare gruppi di base di sistema * 2. Questo va solo un livello profondo della catena rif .. ma può essere fatto in modo ricorsivo - con più codice..

5

Inoltre: alcuni assiemi non vengono caricati immediatamente, quindi è necessario inserire un gestore eventi nell'evento di caricamento dell'assieme di AppDomain.

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

Questa è una davvero vecchia questione, ma per riferimento futuro ecco un'implementazione completa:

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

Bello, grazie per la condivisione, proprio quello di cui avevo bisogno. – Dav

+0

@Dav Prego! –

+0

Provare a utilizzare hashset insteas di un elenco. – AgentFire

Problemi correlati