Bagaimana tepatnya properti "Versi Khusus" dari referensi rakitan bekerja di Visual Studio?

156

Hari ini saya melihat lebih dekat pada properti "Specific Version" referensi perakitan di Visual Studio 2010. Setelah beberapa percobaan dengan hasil yang tidak terduga, saya mulai belajar sebanyak mungkin tentang bagaimana properti bekerja. Bahkan SO, menurut saya, tidak memiliki semua jawaban, jadi inilah upaya saya untuk menjawab sendiri pertanyaan:

Bagaimana tepatnya properti "Versi Khusus" dari referensi rakitan bekerja di Visual Studio?

herzbube
sumber

Jawaban:

255

Ini properti kompilasi!

Salah satu hal terpenting yang perlu diketahui adalah bahwa "Versi Spesifik" adalah properti yang berlaku pada waktu kompilasi dan bukan pada saat runtime.

Tentang apa semua ini?

Ketika sebuah proyek dibangun, referensi perakitan proyek perlu diselesaikan untuk menemukan majelis fisik yang harus digunakan oleh sistem pembangunan. Jika pemeriksaan "Versi Spesifik" dilakukan (lihat bagian "Kapan" Versi Spesifik "dicentang?"), Itu mempengaruhi hasil dari proses resolusi perakitan:

  • Sistem build menempatkan rakitan fisik yang berpotensi digunakan
  • Sistem build membandingkan versi rakitan fisik dengan versi rakitan yang disimpan dalam file .csproj untuk referensi rakitan
  • Jika dua versi rakitan persis sama, proses resolusi berhasil dan rakitan fisik yang ditemukan digunakan untuk membangun
  • Jika dua versi rakitan tidak cocok, rakitan fisik dibuang dan proses resolusi berlanjut dengan mencari rakitan potensial berikutnya
  • Jika tidak ada lagi rakitan fisik potensial, proses resolusi gagal. Ini menghasilkan peringatan kompiler (peringatan MSB3245) yang memberi tahu Anda bahwa referensi tidak dapat diselesaikan.
  • Cukup menarik, build kemudian berlanjut! Jika kode tidak memiliki referensi aktual ke majelis, pembangunan berhasil (dengan peringatan yang disebutkan sebelumnya). Jika kode memiliki referensi, build gagal dengan kesalahan yang terlihat seolah-olah kode tersebut menggunakan tipe atau ruang nama yang tidak dikenal. Satu-satunya indikasi mengapa build benar-benar gagal adalah peringatan MSB3245.

Urutan di mana majelis diselesaikan

Urutan di mana proses resolusi rakitan menempatkan majelis potensial tampaknya adalah sebagai berikut:

  1. Majelis dirujuk oleh <HintPath>elemen dalam file .csproj
  2. Jalur output proyek
  3. GAC

Perhatikan bahwa jika beberapa versi rakitan ada di GAC, proses resolusi pertama-tama mencoba untuk menyelesaikan ke rakitan dengan versi tertinggi. Ini penting hanya jika pemeriksaan "Versi Khusus" tidak dilakukan.

Kapan "Versi Spesifik" dicentang?

Visual Studio mendasarkan keputusannya apakah akan melakukan pemeriksaan "Versi Spesifik" pada dua bagian informasi yang ditemukan dalam file .csproj:

  • Ada atau tidak adanya <SpecificVersion>elemen, dan nilainya (jika ada)
  • Ada atau tidak adanya informasi versi dalam referensi perakitan

Ini adalah bagaimana referensi perakitan umum dengan informasi versi terlihat seperti:

<Reference Include="Foo, Version=1.2.3.4, Culture=neutral, processorArchitecture=MSIL">
  <SpecificVersion>True</SpecificVersion>
  <HintPath>..\..\Bar\Foo.dll</HintPath>
</Reference>

Dan ini adalah bagaimana referensi perakitan terlihat tanpa informasi versi:

<Reference Include="Foo">
[...]

Tabel berikut ini menunjukkan kapan pemeriksaan "Versi Spesifik" dilakukan, dan ketika itu tidak.

                            |     Version information
                            |  Present       Not present
----------------------------+------------------------------
<SpecificVersion>           |
- Present, has value True   |    Yes (1)        Yes (check always fails) (2)
- Present, has value False  |    No  (3)        No (4)
- Not present               |    Yes (5)        No (6)

Yang mengejutkan di sini adalah bahwa tidak ada pemeriksaan yang dilakukan jika keduanya <SpecificVersion>dan informasi versi tidak ada (kasus 6). Saya akan mengharapkan pemeriksaan dilakukan dan selalu gagal (sama seperti kasus 2) karena dalam pemahaman saya tidak adanya <SpecificVersion>menyiratkan nilai default "Benar". Ini mungkin kekhasan Visual Studio 2010 di mana saya melakukan tes saya.

Ketika Anda memeriksa properti referensi perakitan di Visual Studio UI (pilih referensi dan tekan F4), nilai yang Anda lihat untuk properti "Versi Spesifik" memberi tahu Anda apakah Visual Studio akan melakukan "Versi Spesifik" atau tidak. memeriksa. Dalam kasus 6 UI akan menampilkan "True", meskipun <SpecificVersion>elemen tidak ada dalam file .csproj.

Efek samping pada "Salin lokal"

Jika properti "Salin Lokal" diatur ke "Benar" tetapi proses resolusi rakitan gagal karena pemeriksaan "Versi Khusus", tidak ada rakitan yang disalin.

Materi referensi

herzbube
sumber
Terima kasih untuk detailnya. Bisakah saya memeriksa ... memeriksa versi perakitan hanya terjadi untuk majelis dengan nama yang kuat; Apakah itu benar? Juga, ketika kita berbicara tentang memeriksa versi perakitan - adalah bahwa dilakukan dengan membandingkan direferensikan majelis ini nama ? (Dalam kasus majelis yang bernama kuat, nama itu termasuk informasi versi, jadi tidak seperti bidang versi terpisah diperiksa?)
Gavin Hope
2
@GavinHope Pertanyaan 1: Tidak, pemeriksaan versi tidak terbatas pada nama yang kuat, terutama karena nama rakitan dapat menyertakan versi tetapi masih bukan nama yang kuat (misalnya jika ada PublicKeyToken=bagian yang hilang ). Juga, jika Anda memeriksa tabel menjelang akhir posting saya, Anda dapat melihat bahwa pemeriksaan versi dapat terjadi bahkan jika Version=bagian tersebut hilang dari nama rakitan di .csproj. Pertanyaan 2: Saya berasumsi bahwa nama majelis digunakan untuk perbandingan, ya. Saya tidak akan tahu sumber lain untuk informasi tersebut.
herzbube
"Dalam kasus 6 UI akan menampilkan" True ", meskipun elemen <SpecificVersion> tidak ada dalam file .csproj." - Tampaknya nilai default adalah Benar . Setelah mengaktifkan Versi Spesifik di UI ke True , <SpecificVersion>tag dihapus sepenuhnya, yang sebelumnya memiliki nilai False .
samis
@herzbube - Saya pikir arti dari "Versi Spesifik" di jendela Visual Studio> Project Properties adalah kebalikan dari apa yang Anda katakan di sini (yang merupakan kebalikan dari apa yang Anda harapkan). Visual Studio mengatakan bahwa nilai (benar atau salah) dari "Versi Spesifik" "menunjukkan apakah perakitan ini dapat diselesaikan tanpa memperhatikan aturan multi-penargetan untuk resolusi perakitan".
N73k
35

Ketika Anda menambahkan referensi maka Visual Studio merekam [AssemblyVersion] dari perakitan di file proyek. Ini penting. Jika Anda, katakanlah, membuat perbaikan bug setahun kemudian maka Anda ingin memastikan bahwa Anda membangun kembali proyek dengan versi referensi yang sama persis sehingga itu benar-benar sebuah drop-in. Anda akan mendapatkan kesalahan jika rakitan referensi telah berubah.

Tapi itu tidak selalu diinginkan. Beberapa pemrogram membiarkan peningkatan versi perakitan, menghasilkan versi baru setiap kali mereka membangun kembali. Meskipun antarmuka publik majelis tidak pernah berubah. Beberapa mengkonfigurasi proyek mereka dengan menggunakan Nuget untuk mendapatkan perpustakaan dan membiarkannya secara otomatis memperbarui perpustakaan ketika ada rilis baru yang tersedia. Mereka ingin mengatur properti Versi Khusus untuk Salah untuk menekan kesalahan kompilasi.

Cukup penting untuk memahami konsekuensinya, Anda perlu memindahkan kembali seluruh program untuk menghindari kecelakaan. Ketidakcocokan versi saat runtime crash program dan hanya dapat ditekan dengan <bindingRedirect>file .config yang berisiko.

Hans Passant
sumber
2
Terima kasih atas info mengapa "Versi Spesifik" penting, ini adalah teman yang baik untuk aspek mekanis murni yang saya bahas dalam jawaban saya.
herzbube
@Hans Passant - apakah paragraf terakhir Anda valid untuk SpecificVersion Benar atau Salah? Saya pikir ini adalah konsekuensi ketika Anda menetapkannya menjadi benar.
GreenEyedAndy
1
Versi Khusus hanya berlaku untuk membangun aplikasi Anda. Saat runtime, CLR selalu bersikeras pada kecocokan yang tepat dengan nomor versi rakitan referensi. Jika Anda menggunakan versi yang lebih baru pada waktu membangun maka itu juga harus versi yang lebih baru saat runtime.
Hans Passant
1
Waspadai VS2013 & .Net 4.5.1 AutoGenerateBindingRedirects Mereka dapat mengarahkan dll yang mengikat ke versi yang lebih baru meskipun Anda mengatakannya untuk menggunakan versi tertentu
Dennis Kuypers
1
@HansPassant Saya pikir CLR tidak memperhitungkan [AssemblyVersion]ketika majelis tidak ditandatangani nama yang kuat.
tm1