2009-07-27 21 views
6

Ho cercato di rompere questo negli ultimi due settimane e non ho ancora trovato una buona soluzione; spero di poter ottenere una risposta qui.Caricamento di 2 versioni di assembly in fase di esecuzione

Ho due assiemi (ZA & ZB), entrambi i quali puntano a un progetto/dll (ZC) comune ma che potrebbero essere su una versione diversa (vale a dire lo stesso nome dll, stessi spazi dei nomi, alcune classi potrebbero essere differenti) . Ogni assembly funziona da solo, tuttavia, se uno viene caricato dall'altro in fase di esecuzione (ad esempio A carichi B), quindi non riesco a farlo funzionare. Bisogno di aiuto.

Ecco il programma di installazione:

  • ZA dipende ZC versione (comune) 1.1
  • ZB dipende dalla versione ZC 1,0

ZA deve caricare necessità di caricare qualcosa in ZB (che dipende da ZC), in fase di esecuzione.

ZA è l'app principale. Sotto la sua directory bin, c'è una directory di plugin plugins/plugin-ZB con la quale vorrei posizionare tutto ZB e le sue dipendenze (ZC).

Ecco quello che ho provato finora:

Assembly.Load() utilizzando stessa versione di dll - ha funzionato bene.

Assembly.Load() utilizzando diverse versioni di dll - ZB carica, ma quando il metodo viene eseguito, ottengo un metodo non trovato eccezione.

AppDomain.Load() ottenuto un errore di file non trovato; Ho persino usato il delegato per risolvere gli assembly.

Alcuni dettagli relativi a ZC: - alcuni metodi sono pubblici statici (alcuni non lo sono). Per esempio. Log.Log("hello"); - alcuni possono restituire valori (primitivi o oggetti). - alcuni metodi non sono statici (e restituiscono valori).

Aiuto? - TIA

risposta

1

Oltre al consiglio eccellente di Jonathan Allen, un modo più "classico" per risolvere il problema è il caricamento delle 2 versioni in 2 AppDomanis diversi. È quindi possibile utilizzare .NET Remoting per comunicare i due AppDomain. Quindi ZA dovrebbe creare un nuovo Appdomain, caricare in questo ZD AppDomain e richiamare alcune operazioni in ZB tramite Remoting.

Si noti che .NET Remoting ha alcuni requisiti per le classi che si desidera utilizzare (ereditarietà da MarshalByRef) e la creazione di un AppDomain è un'operazione costosa.

Spero che questo aiuto

+0

"Si può avere una sola versione di un assembly per un AppDomain" non è vero. È anche possibile fare riferimento a due versioni di un assieme da un singolo assieme, cercare l'alias extern per maggiori informazioni, ecco la prima cosa che si apre su Google con un esempio della funzione: http://blogs.msdn.com/ b/ansonh/archive/2006/09/28/extern-alias-walkthrough.aspx – Graham

+0

L'utilizzo di due AppDomain è una soluzione al problema descritto. – Graham

+0

Hai ragione, rispondi aggiornato! –

0

Ho avuto due versioni dello stesso assembly caricati allo stesso tempo. È successo con uno scenario proprio come lo descrivi.

È necessario convincere il runtime per caricare la stessa versione di ZC sia per ZA che per ZB. Ho trovato due modi per farlo:

  1. utilizzare un elemento bindingRedirect nel file App.config. Ci sono alcuni dettagli in this question.
  2. Utilizzare l'evento AppDomain.AssemblyResolve. Ci sono alcuni dettagli in this answer.

L'unico problema con AppDomain.AssemblyResolve è che si attiva solo quando il runtime non riesce a trovare la versione richiesta. Se sono disponibili entrambe le versioni, sarà necessario utilizzare lo bindingRedirect. Ho usato l'evento AppDomain.AssemblyResolve e poi ho aggiunto un controllo di sicurezza che assicura che la versione corretta sia stata caricata esaminando la collezione di assiemi di riferimento dell'assieme. Se non lo è, mi lamento con l'utente che una vecchia versione della biblioteca è in giro e dire loro dove si trova.

+1

Questo non sta caricando due versioni diverse, sta caricando la stessa versione due volte. –

+1

Quando ho avuto questo problema, @Cameron, il run time ha caricato la versione 1.1 di ZC all'avvio di ZA. Poi, quando ho caricato il plug-in ZB, il tempo di esecuzione ha caricato la versione 1.0 di ZC con esso. Questo è quello che intendo caricando due diverse versioni. Per fare in modo che ZA e ZB passino gli oggetti da ZC l'uno all'altro, ho dovuto far caricare entrambi la stessa versione di ZC. Questo è quello che sto descrivendo come fare nella mia risposta. Ho frainteso la domanda originale? –

3
m_Assembly1 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "Old Version\Some.dll")) 
    m_Assembly2 = Reflection.Assembly.LoadFile(IO.Path.Combine(System.Environment.CurrentDirectory, "New Version\Some.dll")) 

    Console.WriteLine("Old Version: " & m_Assembly1.GetName.Version.ToString) 
    Console.WriteLine("New Version: " & m_Assembly2.GetName.Version.ToString) 

    m_OldObject = m_Assembly1.CreateInstance("FullClassName") 
    m_NewObject = m_Assembly2.CreateInstance("FullClassName") 

Da qui in avanti ho utilizzato l'associazione tardiva e/o il riflesso per eseguire i miei test.

.NET: Load two version of the same DLL

+0

Consiglio eccellente! non lo sapevo –

Problemi correlati