Perbedaan antara LoadFile dan LoadFrom dengan .NET Assemblies?

126

Saya melihat dokumentasi msdn dan saya masih sedikit bingung tentang apa sebenarnya perbedaan antara menggunakan LoadFiledan LoadFromsaat memuat rakitan. Dapatkah seseorang memberikan contoh atau analogi untuk menggambarkannya dengan lebih baik. Dokumentasi MSDN membuat saya semakin bingung. Juga, Apakah ReflectionOnlyLoadFromsama dengan LoadFromkecuali bahwa itu memuat rakitan hanya dalam mode refleksi.

Karena pengalaman .NET saya bukanlah yang terbaik, berikut adalah beberapa pertanyaan tentang dokumentasi MSDN menggunakan LoadFile:

1) Apa yang dimaksud dengan LoadFilemajelis ujian yang memiliki Identitas yang sama, tetapi berada di jalur yang berbeda? Apa identitas (contoh)?

2) Ini menyatakan LoadFiletidak memuat file ke dalam 'Konteks LoadFrom' dan tidak menyelesaikan ketergantungan menggunakan jalur beban. Artinya, dapatkah seseorang memberikan contoh?

3) Terakhir, ini menyatakan bahwa LoadFileberguna dalam skenario terbatas ini karena LoadFrom tidak dapat memuat rakitan yang memiliki identitas yang sama tetapi jalur yang berbeda; itu hanya akan memuat majelis pertama, yang sekali lagi membawa saya ke pertanyaan yang sama, apa identitas majelis?

Xaisoft
sumber
10
Serius, saya juga berpikir terkadang MS harus mempekerjakan penulis yang lebih baik atau yang lain karena kalimatnya tidak selalu dapat dipahami ...
Tarik
7
Lihat juga undokumentasi
Kolonel Panic
1
@ColonelPanic MS dapat mengatakan bahwa semuanya didokumentasikan ... tetapi dengan faktor bantuan nol.
Legends

Jawaban:

96

Apakah ini menjelaskannya?

// 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);

Sunting : untuk menjawab pertanyaan yang Anda ajukan dalam pertanyaan revisi Anda, Anda pasti ingin membaca Suzanne Cook tentang Identitas Majelis .

Ada banyak aturan yang mengatur bagaimana rakitan dimuat, dan beberapa di antaranya berkaitan dengan cara mereka menyelesaikan dependensi - jika AssemblyA Anda bergantung pada AssemblyB, di mana .NET harus mencari untuk menemukan AssemblyB? Di Cache Majelis Global, direktori yang sama yang ditemukannya AssemblyA, atau di tempat lain seluruhnya? Selain itu, jika menemukan banyak salinan dari rakitan itu, bagaimana cara memilih mana yang akan digunakan?

LoadFrommemiliki satu set aturan, sementara LoadFilememiliki seperangkat aturan lain. Sulit membayangkan banyak alasan untuk menggunakan LoadFile, tetapi jika Anda perlu menggunakan refleksi pada salinan yang berbeda dari rakitan yang sama, itu ada untuk Anda.

Jeff Sternal
sumber
2
Apakah CodeBase sama dengan Identity?
Xaisoft
Tidak, saya baru saja menggunakan CodeBase di sini sebagai properti arbitrer dari assembly untuk menggambarkan bahwa instance Assembly kedua menunjuk ke file 'salah' (dalam contoh pertama). Saya memperbarui jawaban saya dengan lebih detail.
Jeff Sternal
1
Ini membersihkannya sedikit, tetapi bagaimana path1 dan path2 menunjuk ke salinan berbeda dari rakitan yang sama pada disk saat menggunakan LoadFrom dan saat menggunakan LoadFile, path1 dan path2 mengarah ke rakitan yang berbeda. Apa contoh dari path1 dan path2 itu? Terima kasih atas kesabaran Anda.
Xaisoft
Mengapa Anda memeriksa dua referensi string untuk persamaan nilai dengan string.Compare(x, y) == 0? Saya pikir Anda ingin di x == ysana? Jika karena alasan yang tidak jelas Anda benar-benar menginginkan pemeriksaan kesetaraan yang bergantung pada budaya, lebih jelas untuk menulisnya string.Equals(x, y, StringComparison.CurrentCulture), misalnya.
Jeppe Stig Nielsen
@JeffSternal Link di "Suzanne Cook on Assembly Identity" tampaknya rusak di sini ...
Martin Verjans
61

Dari blog Suzanne Cook :

LoadFile vs. LoadFrom

Hati-hati - ini bukan hal yang sama.

LoadFrom () melewati Fusion dan bisa dialihkan ke assembly lain di jalur yang berbeda tetapi dengan identitas yang sama jika sudah dimuat dalam konteks LoadFrom.

LoadFile () sama sekali tidak mengikat melalui Fusion - loader hanya melanjutkan dan memuat * persis seperti yang diminta pemanggil. Itu tidak menggunakan baik konteks Load atau LoadFrom.

Jadi, LoadFrom () biasanya memberi Anda apa yang Anda minta, tetapi belum tentu. LoadFile () adalah untuk mereka yang benar-benar menginginkan apa yang diminta. (* Namun, mulai v2, kebijakan akan diterapkan ke LoadFrom () dan LoadFile (), jadi LoadFile () tidak harus persis seperti yang diminta. Selain itu, mulai dari v2, jika assembly dengan identitasnya ada di GAC, salinan GAC akan digunakan. Gunakan ReflectionOnlyLoadFrom () untuk memuat apa yang Anda inginkan - tetapi, perhatikan bahwa rakitan yang dimuat dengan cara itu tidak dapat dijalankan.)

LoadFile () memiliki tangkapan. Karena tidak menggunakan konteks yang mengikat, dependensinya tidak secara otomatis ditemukan di direktorinya. Jika mereka tidak tersedia dalam konteks Muat, Anda harus berlangganan acara AssemblyResolve untuk mengikatnya.

Lihat disini .

Lihat juga artikel Memilih Konteks yang Mengikat di blog yang sama.

CraigTP
sumber
Terima kasih, saya akan memeriksa blog, saya memperbarui posting saya dengan beberapa pertanyaan tentang dokumentasi msdn.
Xaisoft
@Xaisoft - Blog Suzanne Cook kembali menyelamatkan dengan jawaban dari Identitas Sidang. Lihat blogs.msdn.com/suzcook/archive/2003/07/21/57232.aspx . Ini pada dasarnya adalah "nama tampilan assembly" dan ini seperti: "System, Version = 1.0.3300.0, Culture = neutral, PublicKeyToken = b77a5c561934e089" jadi menyertakan nama sebenarnya assembly, nomor versinya bersama dengan informasi pengenal lainnya (seperti PublicKeyToken dll.).
CraigTP
1
Apa yang dia maksud ketika dia berbicara tentang Fusion?
Xaisoft
1
Memang, Jeff sangat tepat. Lihat tautan ini: grimes.demon.co.uk/workshops/fusionWS.htm untuk tutorial yang bagus tentang sub-sistem Fusion dan teknologinya untuk memuat rakitan di .NET
CraigTP
1
Hanya pembaruan singkat, perhatikan bahwa URL di atas (grimes.demon.co.uk/workshops/fusionWS.htm) tidak lagi valid dan sekarang telah dipindahkan ke: richardgrimes.com/workshops/fusionWS.htm
CraigTP
45

Setelah banyak garuk kepala, saya menemukan perbedaan pada diri saya sore ini.

Saya ingin memuat DLL saat runtime, dan DLL tinggal di direktori lain. DLL itu memiliki dependensinya sendiri (DLL) yang juga tinggal di direktori yang sama.

LoadFile (): Memuat DLL tertentu, tetapi tidak dependensinya. Jadi, ketika panggilan pertama dibuat dari dalam DLL ke salah satu DLL lainnya, itu melemparkan FileNotFoundException.

LoadFrom (): Memuat DLL yang saya tentukan dan juga semua dependensi yang ada di direktori itu.

LordWilmore
sumber
4
Itulah masalah saya! Saya mendapatkan FileNotFoundExceptionsaat membuat instance baru dari objek yang ditentukan dalam assembly yang direferensikan oleh assembly yang baru saja saya muat .LoadFile. Mengubah ini menjadi .LoadFromtampaknya memperbaiki masalah, tetapi saya tidak tahu mengapa! Terima kasih
Connell
1
Terima kasih, saya mengalami masalah yang sama.
Ivandro IG Jao
4

Catatan: Jika satu rakitan dimuat menggunakan jalur 8.3, dan kemudian dari jalur non-8.3, mereka akan terlihat sebagai rakitan yang berbeda, meskipun mereka adalah DLL fisik yang sama.

Gregg DeMasters
sumber
0

satu perbedaan yang saya perhatikan adalah:

Assembly.LoadFile - Memuat assembly di AppDomain berbeda dengan hak pengguna terbatas (prinsip perbedaan). operasi seperti serilisasi / deserilisasi tidak dapat dilakukan.

Assembly.LoadFrom - Memuat assembly di AppDomain yang sama dengan hak pengguna yang sama (prinsip yang sama).

Lalit
sumber
3
Ini tidak benar. Apa yang membuat Anda yakin bahwa Assembly.LoadFile memuat rakitan ke AppDomain lain?
Sven Mawby
0

Dalam kasus saya, saya hanya perlu menghapus cache aplikasi ASP yang terletak @ C:\Windows\Microsoft.NET\Framework\[asp version]\Temporary ASP.NET Files. Itu dibangun kembali saat situs pertama kali dijalankan. Pastikan untuk menghentikan IIS terlebih dahulu.

Semoga ini membantu seseorang seperti itu untuk saya.

David Roth
sumber