.NET 4.0 memiliki GAC baru, mengapa?

300

%windir%\Microsoft.NET\assembly\adalah GAC baru . Apakah ini berarti sekarang kita harus mengelola dua GAC, satu untuk aplikasi .NET 2.0-3.5 dan yang lainnya untuk aplikasi .NET 4.0?

Pertanyaannya adalah, mengapa?

Max Toro
sumber
7
terima kasih telah mengajukan pertanyaan..saya juga sangat bingung ketika saya tidak menemukan gac di lokasi aslinya :)
Jasl
2
Pertanyaan bagus ... Terima kasih banyak.
smwikipedia
1
+1 untuk pertanyaan Anda. Saya mulai pengembangan di bawah NET 4.0 dan bingung dengan masalah "dual" GAC ,.
Hernan
3
Butuh beberapa iterasi, tetapi Microsoft akhirnya membawa DLL Hell ke .NET. Yay!
nothingisnecessary

Jawaban:

181

Ya karena ada 2 Global Assembly Cache (GAC) yang berbeda, Anda harus mengelola masing-masing secara terpisah.

Dalam .NET Framework 4.0, GAC mengalami beberapa perubahan. GAC dibagi menjadi dua, satu untuk setiap CLR.

Versi CLR yang digunakan untuk .NET Framework 2.0 dan .NET Framework 3.5 adalah CLR 2.0. Tidak perlu dalam dua rilis kerangka kerja sebelumnya untuk membagi GAC. Masalah memecah aplikasi yang lebih lama di Net Framework 4.0.

Untuk menghindari masalah antara CLR 2.0 dan CLR 4.0, GAC sekarang dibagi menjadi GAC pribadi untuk setiap runtime. Perubahan utama adalah bahwa aplikasi CLR v2.0 sekarang tidak dapat melihat rakitan CLR v4.0 di GAC.

Sumber

Mengapa?

Tampaknya karena ada perubahan CLR di. NET 4.0 tetapi tidak di 2,0 ke 3,5. Hal yang sama terjadi dengan 1.1 hingga 2.0 CLR. Tampaknya GAC ​​memiliki kemampuan untuk menyimpan versi majelis yang berbeda selama mereka berasal dari CLR yang sama. Mereka tidak ingin merusak aplikasi lama.

Lihat informasi berikut di MSDN tentang perubahan GAC di 4.0 .

Misalnya, jika .NET 1.1 dan .NET 2.0 berbagi GAC yang sama, maka aplikasi .NET 1.1, memuat rakitan dari GAC yang dibagikan ini, dapat memperoleh rakitan .NET 2.0, sehingga merusak aplikasi .NET 1.1

Versi CLR yang digunakan untuk .NET Framework 2.0 dan .NET Framework 3.5 adalah CLR 2.0. Sebagai hasil dari ini, tidak perlu dalam dua rilis kerangka kerja sebelumnya untuk membagi GAC. Masalah melanggar aplikasi yang lebih lama (dalam hal ini, .NET 2.0) muncul kembali di Net Framework 4.0 di mana titik CLR 4.0 dirilis. Oleh karena itu, untuk menghindari masalah interferensi antara CLR 2.0 dan CLR 4.0, GAC sekarang dibagi menjadi GAC pribadi untuk setiap runtime.

Karena CLR diperbarui dalam versi mendatang, Anda dapat mengharapkan hal yang sama. Jika hanya bahasa berubah maka Anda dapat menggunakan GAC yang sama.

Brian R. Bondy
sumber
18
Posting blog itu hanya menyatakan kembali penemuan OP, itu tidak menjelaskan mengapa GAC perlu dibagi. Tidak jelas, GAC asli akan cukup mampu menjaga 4.0 majelis terpisah. Mereka memiliki [AssemblyVersion] baru
Hans Passant
1
@Hans: Mungkin bukan alasan yang tepat tetapi ia mengatakan: "Untuk menghindari masalah antara CLR 2.0 dan CLR 4.0", juga ada 2 pertanyaan di dalamnya. Pertanyaan kedua adalah: "apakah itu artinya sekarang kita harus mengelola dua GAC, satu untuk aplikasi .NET 2.0-3.5 dan yang lainnya untuk aplikasi .NET 4.0?"
Brian R. Bondy
2
Anda harus mengutip ini, dari salah satu tautan Anda: "Misalnya, jika .NET 1.1 dan .NET 2.0 berbagi GAC yang sama, maka aplikasi .NET 1.1, memuat rakitan dari GAC yang dibagikan ini, bisa mendapatkan rakitan .NET 2.0 , dengan demikian merusak aplikasi .NET 1.1. "
Max Toro
67

Saya juga ingin tahu mengapa 2 GAC dan menemukan berikut penjelasan oleh Mark Miller di bagian komentar dari NET 4.0 memiliki 2 Global Assembly Cache (GAC) :

Mark Miller berkata ... 28 Juni 2010 12:13

Terima kasih untuk kirimannya. "Masalah gangguan" sengaja dibuat kabur. Pada saat penulisan, masalah ini masih diselidiki, tetapi jelas ada beberapa skenario yang rusak.

Misalnya, beberapa aplikasi menggunakan Assemby.LoadWithPartialName untuk memuat versi perakitan tertinggi. Jika versi tertinggi dikompilasi dengan v4, maka aplikasi v2 (3.0 atau 3.5) tidak dapat memuatnya, dan aplikasi akan macet, bahkan jika ada versi yang akan berfungsi. Awalnya, kami mempartisi GAC di bawah lokasi aslinya, tetapi itu menyebabkan beberapa masalah dengan skenario pemutakhiran windows. Kedua kode ini melibatkan yang sudah dikirimkan, jadi kami memindahkan (GAC versi-dipartisi ke tempat lain.

Ini seharusnya tidak berdampak pada sebagian besar aplikasi, dan tidak menambah beban pemeliharaan. Kedua lokasi hanya dapat diakses atau dimodifikasi menggunakan API GAC asli, yang sesuai dengan partisi seperti yang diharapkan. Tempat-tempat di mana ini muncul adalah melalui API yang mengekspos jalur GAC seperti GetCachePath, atau memeriksa jalur mscorlib yang dimuat ke dalam kode yang dikelola.

Perlu dicatat bahwa kami memodifikasi lokasi GAC ketika kami merilis v2 juga ketika kami memperkenalkan arsitektur sebagai bagian dari identitas perakitan. Mereka menambahkan GAC_MSIL, GAC_32, dan GAC_64, meskipun semuanya masih di bawah% windir% \ assembly. Sayangnya, itu bukan opsi untuk rilis ini.

Semoga ini membantu pembaca masa depan.

Jasl
sumber
3
Komentar Miller tentang artikel tertaut memang memberikan pandangan orang dalam terhadap topik tersebut.
Nimesh Madhavan
66

Tidak masuk akal, GAC asli sudah cukup mampu menyimpan berbagai versi rakitan. Dan ada sedikit alasan untuk berasumsi bahwa suatu program akan secara tidak sengaja mereferensikan rakitan yang salah, semua rakitan .NET 4 mendapatkan [AssemblyVersion] yang mencapai 4.0.0.0. Fitur sisi-sisi-dalam-proses yang baru tidak boleh mengubah ini.

Dugaan saya: sudah ada terlalu banyak proyek .NET di luar sana yang melanggar aturan "tidak pernah mereferensikan apa pun di GAC secara langsung". Saya sudah melihatnya dilakukan di situs ini beberapa kali.

Hanya satu cara untuk menghindari kerusakan proyek-proyek itu: pindahkan GAC. Back-compat adalah suci di Microsoft.

Hans Passant
sumber
3
Ini adalah satu-satunya jawaban yang mencoba menjelaskan mengapa demikian. +1
Ed S.
1
@Hans Passant: Apa yang Anda maksud dengan aturan "tidak pernah merujuk apa pun di GAC secara langsung"?
Max Toro
2
@ Max: ada dua salinan rakitan .NET di mesin Anda. Itu dimaksudkan untuk menjadi rakitan referensi di c: \ windows \ microsoft.net dan c: \ program files \ rakitan referensi. Dan yang digunakan saat runtime, GAC @ c: \ windows \ assembly. Mereka tidak sama, 64-bit akan menjadi contoh. Microsoft melakukan yang terbaik untuk menghindari orang yang merujuk GAC dengan handler extension shell. Dan dialog Tambahkan Referensi. Tidak 100% efektif
Hans Passant
@Hans Passant: Referensi langsung adalah sesuatu seperti 'c: \ WINDOWS \ assembly \ GAC_MSIL \ System \ 2.0.0.0__b77a5c561934e089 \ System.dll', saya tidak melihat bagaimana menambahkan versi baru akan merusak referensi itu.
Max Toro
2
@Hans Passant: "Dan ada sedikit alasan untuk menganggap suatu program akan pernah secara tidak sengaja merujuk majelis yang salah" Saya kira kuncinya di sini adalah Assembly.LoadWithPartialName, apa yang terjadi jika kita memiliki 2 versi perakitan di GAC?
Max Toro