Версія версій збірок у .NET може бути заплутаною перспективою, враховуючи, що в даний час існує щонайменше три способи визначення версії для вашої збірки.
Ось три основні атрибути збірки, пов’язані з версією:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
За угодою, чотири частини версії називаються як Major Version , Minor Version , Будувати і Revision .
AssemblyFileVersion
Призначений для однозначної ідентифікації збірки з індивідуальної збірки
Зазвичай ви вручну встановлюєте Major and Minor AssemblyFileVersion для відображення версії збірки, а потім збільшуєте збірку та / або перегляд кожного разу, коли ваша система збирання збирає збірку. AssemblyFileVersion повинен дозволяти вам однозначно ідентифікувати збірку збірки, щоб ви могли використовувати її як вихідну точку для налагодження будь-яких проблем.
У моєму поточному проекті ми маємо сервер збірки, що кодує номер списку змін з нашого сховища керування джерелами у частинах зборки та редагування AssemblyFileVersion. Це дозволяє нам відображати безпосередньо зі збірки до його вихідного коду для будь-якої збірки, створеної сервером збірки (без необхідності використання міток або гілок у керуванні джерелом або вручну зберігати будь-які записи випущених версій).
Цей номер версії зберігається у ресурсі версії Win32 і його можна побачити під час перегляду сторінок властивостей Windows Explorer для складання.
CLR не переймається і не вивчає AssemblyFileVersion.
Це AssemblyInformationalVersion
призначено для представлення версії всього вашого продукту
AssemblyInformationalVersion призначений для того, щоб дозволити послідовну версію всього продукту, яка може складатися з безлічі збірок, які незалежно розроблені, можливо, з різними політиками версій і потенційно розроблені різними командами.
«Наприклад, версія 2.0 продукту може містити кілька збірок; одна з цих збірок позначена як версія 1.0, оскільки це нова збірка, яка не постачається у версії 1.0 того ж продукту. Зазвичай ви встановлюєте основні та другорядні частини цього номера версії, щоб представити загальнодоступну версію вашого продукту. Потім ви збільшуєте деталі для складання та ревізії кожного разу, коли ви пакуєте повний продукт із усіма його збірками ». - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 57
CLR не переймається і не вивчає Асамблейську інформаційну версію.
AssemblyVersion
Є єдиною версією , що CLR піклується про (але піклується про все AssemblyVersion
)
CLR використовується AssemblyVersion для прив'язки до сильно названих збірок. Він зберігається у таблиці метаданих маніфесту AssemblyDef вбудованої збірки та в таблиці AssemblyRef будь-якої збірки, на яку посилається.
Це дуже важливо, оскільки це означає, що коли ви посилаєтесь на чітко названу збірку, ви щільно прив'язані до конкретної AssemblyVersion цієї збірки. Весь AssemblyVersion повинен відповідати точності, щоб обов'язковість пройшла успішно. Наприклад, якщо ви посилаєтесь на версію 1.0.0.0 сильно названої збірки під час збирання, але лише версія 1.0.0.1 цієї збірки доступна під час виконання, прив'язка не вдасться! (Тоді вам доведеться обійти це, використовуючи перенаправлення прив'язки .)
Плутанина щодо того, чи AssemblyVersion
має збігатися весь . (Так.)
Існує невелика плутанина навколо того, чи повинен цілий AssemblyVersion точно відповідати, щоб збірка була завантажена. Деякі люди знаходять помилкове переконання, що лише основна та менша частини Асамблеї Версії повинні відповідати, щоб обов'язковість пройшла успішно. Це розумне припущення, однак воно в кінцевому підсумку невірно (як .NET 3.5), і перевірити це для вашої версії CLR тривіально. Просто виконайте цей зразок коду .
На моїй машині навантаження на другу збірку виходить з ладу, і в останніх двох рядках журналу плавлення чітко видно, чому:
.NET Framework Version: 2.0.50727.3521
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
Successfully loaded assembly: Rhino.Mocks, Version=3.5.0.1337, Culture=neutral, PublicKeyToken=0b3305902db7183f
---
Attempting to load assembly: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
Assembly binding for failed:
System.IO.FileLoadException: Could not load file or assembly 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral,
PublicKeyToken=0b3305902db7183f' or one of its dependencies. The located assembly's manifest definition
does not match the assembly reference. (Exception from HRESULT: 0x80131040)
File name: 'Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f'
=== Pre-bind state information ===
LOG: User = Phoenix\Dani
LOG: DisplayName = Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
(Fully-specified)
LOG: Appbase = [...]
LOG: Initial PrivatePath = NULL
Calling assembly : AssemblyBinding, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null.
===
LOG: This bind starts in default load context.
LOG: No application configuration file found.
LOG: Using machine configuration file from C:\Windows\Microsoft.NET\Framework64\v2.0.50727\config\machine.config.
LOG: Post-policy reference: Rhino.Mocks, Version=3.5.0.1336, Culture=neutral, PublicKeyToken=0b3305902db7183f
LOG: Attempting download of new URL [...].
WRN: Comparing the assembly name resulted in the mismatch: Revision Number
ERR: Failed to complete setup of assembly (hr = 0x80131040). Probing terminated.
Я думаю, що джерело цієї плутанини, мабуть, пов'язане з тим, що Microsoft спочатку мав бути трохи поблажливішим до цього суворого відповідності повної версії AssemblyVersion, співставляючи лише основні та малі версії:
"Під час завантаження збірки CLR автоматично знайде останню встановлену версію обслуговування, що відповідає основній / другорядній версії запитуваної збірки." - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 56
Така поведінка в Beta 1 1.0 CLR, однак ця функція була видалена до випуску 1.0, і не вдалося повторно вийти на поверхню в .NET 2.0:
"Примітка. Я щойно описав, як ви повинні думати номери версій. На жаль, CLR не розглядає номери версій таким чином. [In .NET 2.0], CLR розглядає номер версії як непрозоре значення, і якщо збірка залежить від версії 1.2.3.4 іншої збірки, CLR намагається завантажити лише версію 1.2.3.4 (якщо не має місце переадресація прив'язки ). Однак
Microsoft планує змінити завантажувач CLR у майбутній версії, щоб він завантажував останню збірку / версію для даної основної / другорядної версії збірки. Наприклад, у майбутній версії CLR, якщо завантажувач намагається знайти версію 1.2.3.4 збірки, а версія 1.2.5.0 існує, завантажувач автоматично підбирає останню версію обслуговування. Це буде дуже вітальною зміною завантажувача CLR - я за те, що не можу чекати ». - Джеффрі Ріхтер, [CLR через C # (друге видання)] стор. 164 (акцент міна)
Оскільки ця зміна досі не була здійснена, я вважаю, що з впевненістю можна припустити, що компанія Microsoft відслідковувала цей намір, і зараз, можливо, пізно змінити це. Я спробував пошукати в Інтернеті, щоб дізнатися, що сталося з цими планами, але я не зміг знайти відповіді. Я все-таки хотів дійти до цього.
Тож я надіслав електронною поштою Джеффу Ріхтеру і запитав його прямо - я зрозумів, що хтось знає, що сталося, це буде він.
Він відповів не менше ніж на 12 годин у суботу вранці, і уточнив, що завантажувач .NET 1.0 Beta 1 реалізував цей механізм "автоматичного відкоту" для підбору останньої доступної збірки та перегляду збірки, але така поведінка була повернено раніше. NET 1.0 поставляється. Пізніше планувалося відродити це, але він не встиг перед тим, як з'явиться CLR 2.0. Потім з'явився Silverlight, який став пріоритетним для команди CLR, тому ця функціональність ще більше затрималася. Тим часом більшість людей, які були в часи CLR 1.0 Beta 1, з тих пір перейшли, тому навряд чи це побачить світло дня, незважаючи на всю наполегливу роботу, яка вже була вкладена в нього.
Нинішня поведінка, здається, тут залишається.
Варто також відзначити з мого обговорення з Jeff, що AssemblyFileVersion було додано лише після видалення механізму "автоматичного прокрутки", тому що після 1.0 Beta 1 будь-яка зміна AssemblyVersion була переломною зміною для ваших клієнтів. ніде безпечно зберігати номер складання. AssemblyFileVersion - це безпечний притулок, оскільки він ніколи не перевіряється автоматично CLR. Можливо, це зрозуміліше, маючи два окремі номери версій, з окремими значеннями, а не намагатися зробити це розмежування між майором / мінором (розривом) та складанням / переглядом (нерозривних) частин асамблеї Версії.
Підсумок: ретельно подумайте, коли ви зміните свій AssemblyVersion
Мораль полягає в тому, що якщо ви відправляєте збірки, на які збираються посилатися інші розробники, вам потрібно бути дуже обережним щодо того, коли ви (і не робите) змінити AssemblyVersion цих збірок. Будь-які зміни в AssemblyVersion означатимуть, що розробникам додатків доведеться або перекомпілювати проти нової версії (для оновлення цих записів AssemblyRef), або використовувати переадресації збірки прив'язки, щоб вручну змінити прив'язку.
- Не змінюйте AssemblyVersion на сервісний випуск, який повинен бути сумісним назад.
- Як змінити AssemblyVersion для випуску , що ви знаєте , мають відмінності.
Просто погляньте ще на атрибути версії на mscorlib:
// Assembly mscorlib, Version 2.0.0.0
[assembly: AssemblyFileVersion("2.0.50727.3521")]
[assembly: AssemblyInformationalVersion("2.0.50727.3521")]
[assembly: AssemblyVersion("2.0.0.0")]
Зауважте, що саме AssemblyFileVersion містить всю цікаву інформацію про обслуговування (саме частина Revision цієї версії розповідає про те, який пакет оновлень ви працюєте), тим часом AssemblyVersion встановлюється на нудному старому 2.0.0.0. Будь-яка зміна AssemblyVersion змусить усі програми .NET, що посилаються на mscorlib.dll, перекомпілювати з нової версії!