Як саме функціонує властивість „Конкретна версія” посилання на збірку у Visual Studio?


155

Сьогодні я детальніше ознайомився з властивістю "Специфічної версії" посилань на збирання у Visual Studio 2010. Після кількох експериментів з несподіваними результатами я поставив собі за мету дізнатися якнайбільше про те, як працює цей ресурс. Навіть ТАК, мені здається, не має всіх відповідей, тож ось моя спроба самостійно відповісти на питання:

Як саме працює властивість "Конкретна версія" збірки довідок у Visual Studio?

Відповіді:


255

Це властивість часу компіляції!

Однією з найважливіших речей, яку потрібно знати, є те, що "Конкретна версія" - це властивість, яка набуває чинності під час компіляції, а не під час виконання.

Про що це все?

Коли проект будується, посилання на складання проекту повинні бути вирішені, щоб знайти фізичні збірки, якими повинна використовувати система збирання. Якщо перевірка "Конкретної версії" виконується (див. Розділ "Коли перевіряється" Конкретна версія "?"), Це впливає на результат процесу вирішення монтажу:

  • Система збирання знаходить фізичну збірку, яку вона потенційно може використовувати
  • Система збірки порівнює версію фізичної збірки з версією збірки, що зберігається у файлі .csproj для посилання на збірку
  • Якщо дві версії збірки абсолютно однакові, процес роздільної здатності успішний, і знайдена фізична збірка використовується для збірки
  • Якщо дві версії збірки не збігаються, фізична збірка відміняється, і процес роздільної здатності триває шляхом знаходження наступної потенційної збірки
  • Якщо більше потенційних фізичних вузлів не може бути розміщено, процес роздільної здатності не вдається. Це призводить до попередження компілятора (попередження MSB3245), яке повідомляє, що посилання неможливо було вирішити.
  • Цікаво, що збірка продовжується! Якщо в коді немає фактичних посилань на збірку, збірка вдається (з попередньо згаданим попередженням). Якщо в коді є посилання, збірка не вдається з помилкою, схожою на те, що в коді використовуються невідомі типи або простори імен. Єдине свідчення, чому збірка дійсно не вдалася, - це попередження MSB3245.

Порядок, в якому вирішуються збірки

Порядок, в якому процес роздільної здатності збирання знаходить потенційні збірки, виглядає таким:

  1. Вузол , на який посилається <HintPath>елемент в файлі .csproj
  2. Шлях виведення проекту
  3. GAC

Зауважте, що якщо в GAC існує декілька версій збірки, процес роздільної здатності спочатку намагається вирішити цю збірку з найвищою версією. Це важливо лише в тому випадку, якщо перевірка "Конкретна версія" не робиться.

Коли перевіряється "Конкретна версія"?

Visual Studio базує своє рішення про те, чи слід перевірити "конкретну версію" на двох відомостях, знайдених у файлі .csproj:

  • Наявність або відсутність <SpecificVersion>елемента та його значення (якщо він присутній)
  • Наявність або відсутність інформації про версію в довідці про збірку

Ось як виглядає типова посилання на збірку з інформацією про версію:

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

Ось так виглядає посилання на збірку без інформації про версію:

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

Наступна таблиця показує, коли виконується перевірка "Конкретної версії" та коли її немає.

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

Дивним є те, що перевірка не виконується, якщо <SpecificVersion>і інформація про версію відсутня (випадок 6). Я б очікував, що перевірка буде виконана і завжди буде невдалою (так само, як і у випадку 2), оскільки, наскільки я розумію, відсутність <SpecificVersion>передбачає значення за замовчуванням "True". Це може бути вигадка Visual Studio 2010, де я робив свої тести.

Коли ви вивчаєте властивості посилання на збірку в інтерфейсі Visual Studio (виберіть посилання та натисніть F4), значення, яке ви бачите для властивості "Конкретна версія", повідомляє вам, чи збирається Visual Studio виконувати "Конкретну версію" перевірити. У випадку 6 користувальницький інтерфейс покаже "True", хоча <SpecificVersion>елемент відсутній у файлі .csproj.

Побічні ефекти для "Копіювати локальний"

Якщо для властивості "Copy Local" встановлено значення "True", але процес роздільної здатності збірки не вдається через перевірку "Specific Version", жодна збірка не копіюється.

Довідковий матеріал


Дякую за деталі. Чи можу я просто перевірити ... перевірка версії збірки відбувається лише для збірок із сильними назвами; це так? Крім того , коли ми говоримо про перевірку версії збірки - це робиться шляхом порівняння довідкових Асамблей імені ? (У разі сильної назви збірки це ім’я включає інформацію про версію, тож не схоже, що перевіряється окреме поле версії?)
Гевін Надія,

2
@GavinHope Запитання 1: Ні, перевірка версії не обмежується сильними іменами, головним чином тому, що назва збірки може містити версію, але все ж не є сильною назвою (наприклад, якщо в ній відсутня PublicKeyToken=частина). Крім того, якщо ви перевірите таблицю наприкінці моєї публікації, ви можете побачити, що перевірка версії може відбутися, навіть якщо Version=частина відсутня в назві збірки в .csproj. Питання 2: Я припускаю, що назва порівняння використовується для порівняння, так. Я б не знав жодного іншого джерела інформації.
herzbube

"У випадку 6 інтерфейс покаже" True ", хоча елемент <SpecificVersion> у файлі .csproj відсутній." - Здається, що типовим значенням є True . Після перемикаючи конкретної версії в інтерфейсі в True<SpecificVersion> , тег був повністю опущений, який раніше мав значення Брехня .
Саміс

@herzbube - Я думаю, що значення "конкретної версії" у вікні Visual Studio> Властивості проекту є протилежним тому, що ви тут говорите (що протилежне тому, що ви очікували). Visual Studio каже, що значення (істинне або хибне) "конкретної версії" "вказує, чи може ця збірка бути вирішена без урахування правил багатоцільового націлення на дозвіл збірки".
N73k

35

Коли ви додаєте посилання, Visual Studio записує [AssemblyVersion] збірки у файл проекту. Це важливо. Якщо ви, скажімо, створили виправлення помилок через рік пізніше, тоді ви хочете переконатися, що ви відновите проект із точно такою ж версією посилання, щоб це було справжньою програмою. Ви отримаєте помилку, якщо довідкова збірка змінилася.

Але це не завжди бажано. Деякі програмісти дозволяють автоматично збільшити версію збірки, генеруючи нову версію кожного разу, коли вони відновлюються. Навіть незважаючи на те, що публічний інтерфейс зборів ніколи не змінювався. Деякі налаштовують свій проект, використовуючи Nuget для отримання бібліотек, і дозволяють йому автоматично оновлювати бібліотеку, коли є новий випуск. Їм подобається встановити властивість Specific Version на False, щоб придушити помилку компіляції.

Дуже важливо, щоб зрозуміти наслідок, вам потрібно переробити всю складову програми, щоб уникнути аварій. Невідповідність версій під час виконання програми збоїв у програмі і може бути придушена лише <bindingRedirect>за допомогою файлу .config, який є ризиковим.


2
Дякую за інформацію, чому "Конкретна версія" важлива, це хороший супутник чисто механічним аспектам, які я висвітлюю у своїй відповіді.
herzbube

@Hans Passant - чи є ваш останній абзац справжнім чи хибним SpecificVersion? Я думаю, що це наслідки, коли ви встановите це на істину.
GreenEyedAndy

1
SpecificVersion стосується лише створення вашої програми. Під час виконання CLR завжди наполягає на точній відповідності номеру версії еталонної збірки. Якщо ви використовували нову версію під час збирання, тоді вона повинна бути і новою версією під час виконання.
Ганс Пасант

1
Остерігайтеся VS2013 & .Net 4.5.1 AutoGenerateBindingRedirects Вони можуть перенаправити прив’язку dll до нової версії, навіть якщо ви сказали їй використовувати конкретну версію
Dennis Kuypers

1
@HansPassant Я вважав, що CLR не враховує, [AssemblyVersion]коли збірки не підписують сильне ім'я.
tm1
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.