Differenza tra LoadFile e LoadFrom con gli assembly .NET?


126

Stavo guardando la documentazione di msdn e sono ancora un po 'confuso su quale sia esattamente la differenza tra l'utilizzo LoadFilee il LoadFromcaricamento di un assembly. Qualcuno può fornire un esempio o un'analogia per descriverlo meglio. La documentazione MSDN mi ha confuso di più. Inoltre, è ReflectionOnlyLoadFromuguale LoadFromall'eccezione del fatto che carica l'assieme solo in modalità riflessione.

Poiché la mia esperienza .NET non è la migliore, ecco alcune domande relative alla documentazione MSDN che utilizza LoadFile:

1) Cosa significa LoadFileesaminando assemblee che hanno la stessa identità, ma che si trovano in percorsi diversi? Qual è l'identità (esempio)?

2) Indica LoadFileche non carica i file nel 'Contesto LoadFrom' e non risolve le dipendenze usando il percorso di caricamento. Cosa significa questo, qualcuno può fornire un esempio?

3) Infine, afferma che LoadFileè utile in questo scenario limitato perché LoadFrom non può caricare assembly che hanno le stesse identità ma percorsi diversi; caricherà solo il primo di questi assembly, il che mi porta ancora alla stessa domanda, qual è l'identità degli assembly?


10
Seriamente penso anche che a volte la SM dovrebbe assumere scrittori migliori o qualcos'altro dato che le frasi non sono sempre comprensibili ...
Tarik


1
@ColonelPanic MS può dire che tutto è documentato ... ma con un fattore di aiuto di zeroooo.
Leggende

Risposte:


96

Questo lo chiarisce?

// path1 and path2 point to different copies of the same assembly on disk:

Assembly assembly1 = Assembly.LoadFrom(path1);
Assembly assembly2 = Assembly.LoadFrom(path2);

// These both point to the assembly from path1, so this is true
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

assembly1 = Assembly.LoadFile(path1);
assembly2 = Assembly.LoadFile(path2);

// These point to different assemblies now, so this is false
Console.WriteLine(assembly1.CodeBase == assembly2.CodeBase);

Modifica : per rispondere alle domande che hai sollevato nella tua domanda rivista, devi assolutamente leggere Suzanne Cook su Assembly Identity .

Esistono molte regole che regolano il modo in cui vengono caricati gli assembly e alcuni di essi hanno a che fare con il modo in cui risolvono le dipendenze: se AssemblyA dipende da AssemblyB, dove dovrebbe cercare .NET per trovare AssemblyB? Nella Global Assembly Cache, la stessa directory che ha trovato AssemblyA o da qualche altra parte del tutto? Inoltre, se trova più copie di quell'assieme, come dovrebbe scegliere quale utilizzare?

LoadFrom ha un insieme di regole, mentre LoadFile ha un altro set di regole. È difficile immaginare molte ragioni da usare LoadFile, ma se hai bisogno di usare la riflessione su diverse copie dello stesso assieme, è lì per te.


2
CodeBase è uguale all'identità?
Xaisoft,

No, ho appena usato CodeBase qui come proprietà arbitraria dell'assembly per illustrare che la seconda istanza di Assembly puntava al file "errato" (nel primo esempio). Sto aggiornando la mia risposta con maggiori dettagli.
Jeff Sternal,

1
Lo chiarisce un po ', ma in che modo path1 e path2 puntano a diverse copie dello stesso assembly su disco quando si utilizza LoadFrom e quando si utilizza LoadFile, path1 e path2 puntano a diversi assembly. Qual è un esempio di cosa sarebbero path1 e path2? Grazie per la vostra pazienza.
Xaisoft,

Perché controlli due riferimenti di stringa per l'uguaglianza dei valori con string.Compare(x, y) == 0? Penso che tu voglia x == ylì? Se per ragioni oscure vuoi un controllo dell'uguaglianza dipendente dalla cultura, è più chiaro scrivere string.Equals(x, y, StringComparison.CurrentCulture), per esempio.
Jeppe Stig Nielsen,

@JeffSternal Link su "Suzanne Cook su Assembly Identity" sembra essere rotto qui ...
Martin Verjans

61

Dal blog di Suzanne Cook :

LoadFile vs. LoadFrom

Fai attenzione: non sono la stessa cosa.

LoadFrom () passa attraverso Fusion e può essere reindirizzato a un altro assembly in un percorso diverso ma con la stessa identità se uno è già caricato nel contesto LoadFrom.

LoadFile () non si collega affatto a Fusion: il caricatore procede e carica esattamente * ciò che il chiamante ha richiesto. Non utilizza il contesto Load o LoadFrom.

Quindi, LoadFrom () di solito ti dà quello che hai chiesto, ma non necessariamente. LoadFile () è per coloro che vogliono davvero esattamente ciò che è richiesto. (* Tuttavia, a partire dalla v2, i criteri verranno applicati sia a LoadFrom () che a LoadFile (), quindi LoadFile () non sarà necessariamente esattamente ciò che è stato richiesto. Inoltre, a partire da v2, se un assembly con la sua identità è in al posto del GAC, verrà invece utilizzata la copia del GAC. Utilizzare ReflectionOnlyLoadFrom () per caricare esattamente ciò che si desidera, ma si noti che gli assembly caricati in questo modo non possono essere eseguiti.)

LoadFile () ha un problema. Poiché non utilizza un contesto vincolante, le sue dipendenze non vengono trovate automaticamente nella sua directory. Se non sono disponibili nel contesto di caricamento, è necessario abbonarsi all'evento AssemblyResolve per associarsi a loro.

Vedi qui .

Vedi anche Scelta di un articolo di contesto vincolante sullo stesso blog.


Grazie, controllerò il blog, ho aggiornato il mio post con alcune domande sulla documentazione msdn.
Xaisoft,

@Xaisoft - Il blog di Suzanne Cook torna in soccorso con la risposta di un'Assemblea delle identità. Vedi blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx . È essenzialmente un "nome visualizzato dell'assembly" e questo è qualcosa del tipo: "Sistema, Versione = 1.0.3300.0, Cultura = neutro, PublicKeyToken = b77a5c561934e089" quindi include sia il nome effettivo dell'assembly, sia il numero di versione insieme ad altre informazioni identificative (come PublicKeyToken ecc.).
CraigTP,

1
A cosa si riferisce quando parla di Fusion?
Xaisoft,

1
In effetti, Jeff è perfetto. Vedi questo link: grimes.demon.co.uk/workshops/fusionWS.htm per un bel tutorial sul sottosistema Fusion e la sua tecnologia per caricare gli assembly in .NET
CraigTP

1
Solo un rapido aggiornamento, nota che l'URL sopra (grimes.demon.co.uk/workshops/fusionWS.htm) non è più valido e ora è passato a: richardgrimes.com/workshops/fusionWS.htm
CraigTP

45

Dopo un sacco di grattacapi, ho scoperto anch'io una differenza questo pomeriggio.

Volevo caricare una DLL in fase di esecuzione e la DLL viveva in un'altra directory. Quella DLL aveva le sue dipendenze (DLL) che vivevano anche nella stessa directory.

LoadFile (): caricato la DLL specifica, ma non le dipendenze. Quindi, quando la prima chiamata è stata effettuata dall'interno della DLL a una di quelle altre DLL ha generato FileNotFoundException.

LoadFrom (): caricato la DLL che ho specificato e anche tutte le dipendenze che risiedevano in quella directory.


4
Quello era esattamente il mio problema! Stavo ottenendo il risultato FileNotFoundExceptiondurante la creazione di una nuova istanza di un oggetto definito in un assembly a cui fa riferimento l'assembly che avevo appena caricato .LoadFile. Modificarlo per .LoadFromsembrare risolto il problema, ma non sapevo perché! Grazie
Connell il

1
Grazie, stavo avendo lo stesso problema.
Ivandro IG Jao,

4

Nota: se un assembly viene caricato utilizzando un percorso 8.3, quindi da un percorso non 8.3, verranno visualizzati come assembly diversi, anche se si tratta della stessa DLL fisica.



0

una differenza che ho notato è:

Assembly.LoadFile : carica l'assembly in diversi AppDomain con diritti utente limitati (principio di diffrenza). non è stato possibile eseguire operazioni come serilizzazione / deserilizzazione.

Assembly.LoadFrom : carica l'assembly nello stesso AppDomain con gli stessi diritti utente (stesso principio).


3
Questo non è corretto Cosa ti fa credere che Assembly.LoadFile carica un assembly in un altro AppDomain?
fr34kyn01535

0

Nel mio caso, ho dovuto semplicemente eliminare la cache dell'applicazione ASP situata @ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. Viene ricostruito al primo avvio del sito. Assicurati di interrompere prima IIS.

Spero che questo aiuti qualcuno come ha fatto per me.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.