ПРИМЕЧАНИЕ
Хотя здесь надо оговориться: к любому приложению может быть применена политика версий, которая принудительно его заставит использовать указанную в политике сборку.
Поиск в глобальном хранилище сборок идет, основываясь на строгих сведениях о версии, что позволяет избегать многих проблем, описанных ранее. Для повышения надежности и стойкости системы GAC, вы не сможете производить какие либо действия (кроме, конечно, простого просмотра) с глобальным хранилищем, если вы не будете иметь прав администратора. Такая политика введена по умолчанию в отношении GAC, хотя при желании ее можно будет изменить. А что это вообще означает? Тут, на самом деле, все интереснее, чем могло бы показаться с первого взгляда. Смысл данной политики таков: пользователь, не имеющий прав администратора, не сможет как-либо повлиять на работу приложений, установленных в системе, хотя и сможет устанавливать приложения, но лишь те, которые не будут использовать совместных сборок. Иными словами, ничего глобального простому пользователю испортить не удастся.
Как "работает" информация о версиях
Сама версия состоит из четырёх чисел; для наглядности, пожалуй, даже нарисую.
Рис. 5
На практике это выглядит, к примеру, так: 1.0.2.3. Где:
• Major– основная версия.
• Minor– подверсия приложения.
• Build– количество построений (полных компиляций) для данной версии.
• Revision– Номер ревизии для текущего построения.
В версии выделяется основная часть и дополнительная. При поиске нужной сборки, основная часть версии должна строго совпадать, а с дополнительной частью всё происходит хитрее. Если будет найдено несколько сборок с одинаковыми основными частями, то будет выбрана сборка с наибольшей дополнительной частью. Версию сборки вы можете задать при помощи параметра командной строки либо при помощи атрибута System.Reflection.AssemblyVersionAttribute. Здесь, правда, есть одна хитрость: вы можете задавать версию не полностью, а только ее часть. К примеру вот так: "1.*","1.5.*,@1.5.2.*". При отсутствии каких либо частей, компилятор допишет их сам по следующим правилам:
• Minor– приравнивается к нулю
• Build– приравнивается количеству дней прошедших с первого января 2000 года
• Revision– приравнивается количеству секунд, прошедших с полуночи, деленных на два.
Такая, казалось бы, странная схемы выбрана далеко не случайно: она позволяет гарантировать уникальность версии для каждого построения приложения, что, вообщем-то, немаловажно.
Технологи прямого запуска (Side-By-Side Execution)
Я долго думал, как на словах описать эту технологию, но что-то ничего не лезло в голову, поэтому я решил нарисовать. Думаю, что, посмотрев на рисунок, вы сразу многое поймёте. Главное, обратите внимание на версии.
Рис. 6
Идея состоит в том, что для одного и того же приложения могут быть загружены разные версии одной и той же сборки, и при этом оно ничего не будет знать об этом. Для примера, библиотеки, обозначенные на рисунке цифрами 1 и 2, будут загружены для нашего приложения и может даже будут одновременно работать, но ни одна из них не узнает о существовании другой, что позволит избежать каких-либо конфликтов.
ПРЕДУПРЕЖДЕНИЕ
Не все так хорошо, как могло показаться. Да, система CLR не допустит прямых конфликтов между сборками разных версий, но приложение-то по-прежнему исполняется прежде всего операционной системой, а не CLR. И надо обязательно учитывать тонкости ОС, чтобы избежать проблем. К примеру, мы создаем именований объект ядра с некоторым именем, пускай это будет проецируемый в память файл. Все вроде кажется нормально, но тут подгружается в память другая версия нашей же библиотеки, и создает проецируемый в память файл с таким же именем. И что? А то, что для него не создается новый файл, а открывается уже существующий, созданный ранее другой версией нашей библиотеки. Думаю, вы сами можете себе представить, что при этом может произойти. При проектировании ваших собственных сборок вы должны обязательно помнить о таких, казалось бы, незначительных вещах. Это позволит вам в будущем избежать множества неприятных проблем.
Читать дальше