ЯЗЫК ПРОГРАММИРОВАНИЯ С# 2005 И ПЛАТФОРМА .NET 2.0. 3-е издание - Эндрю Троелсен
Шрифт:
Интервал:
Закладка:
‹dependentAssembly›
‹assemblyIdentity name="CarLibrary" publicKeyToken="l91ebf55656e0a43" /›
‹publisherPolicy аррlу="yes" /›
‹bindingRedirect oldVersion= "1.0.0.0" newVersion="2.0.0.0" /›
‹/dependentAssembly›
‹/assemblyBinding›
‹/runtime›
‹/configuration›
Анализ внутренней структуры GAC
Итак, все работает. Теперь давайте посмотрим на внутреннюю структуру GAC. При просмотре папки GAG в программе Проводник Windows вы видите ряд пиктограмм, изображающих каждый из общедоступных компоновочных блоков всех имеющихся версий. Эта графическая оболочка обеспечивается COM-сервером shfusion.dll. Но, как вы можете подозревать, за этими пиктограммами должна скрываться сложная (хотя и вполне логичная) структура каталогов.
Чтобы понять, что на самом деле представляет собой структура GAC, откройте окно командной строки и перейдите в каталог assembly.
cd c:windowsassembly
Выберите в командной строке команду dir. В этом каталоге, среди прочего, вы обнаружите папку с названием GAC_MISL (рис. 11.26).
Рис. 11.26. Скрытый подкаталог GAC_MSIL
Перейдите в каталог GAC_MSIL и снова выберите команду dir. Теперь вы увидите список подкаталогов, которые имеют в точности такие же имена, как и пиктограммы, отображаемые сервером shfusion.dll. Перейдите в подкаталог CarLibrary и снова выберите команду dir (рис. 11.27).
Рис. 11.27. Внутри скрытого подкаталога CarLibrary
Как видите, в структуре GAC для каждой версии общедоступного компоновочного блока создается свой подкаталог, имя которого выбирается по правилу ‹версияКомпоновочногоБлока›__кодОткрытогоКлюча. Если из текущего каталога вы перейдете в каталог CarLibrarу версии 1.0.0.0, то обнаружите там копию соответствующей библиотеки программного кода (рис .11.28).
Рис. 11.28. Смотрите! Внутренняя копия GAC библиотеки CarLibrary.dll!
При установке строго именованного компоновочного блока в структуру GAC операционная система расширяет структуру путем создания специального подкаталога в системном каталоге assembly. При таком подходе среда CLR может использовать разные версии, компоновочных блоков, избегая конфликтов, которые иначе могли бы возникать из-за наличия файлов *.dll с одинаковыми названиями.
Файлы политики публикации компоновочных блоков
Следующий вопрос, который мы должны рассмотреть в рамках обсуждения возможностей конфигурации, это роль политики публикации компоновочных блоков. Вы только что убедились, что с помощью файлов *.config можно выполнить привязку к конкретной версии общедоступного компоновочного блока в обход версии, указанной в манифесте клиента. Все это просто прекрасно, но представьте себе, что вы являетесь администратором, которому придется переконфигурировать все приложения клиента на данной машине так, чтобы эти приложения использовали компоновочный блок CarLibrary.dll версии 2.0.0.0. Ввиду принятого соглашения для имен файлов конфигурации, вам придется многократно копировать одно и то же XML-содержимое во множество мест (еще и предполагается, что вы должны знать, где находятся все файлы, использующие CarLibrary!). Очевидно, что для администратора это будет просто кошмаром.
Политика публикации позволяет "издателю" данного компоновочного блока (вам, вашему подразделению, вашей компании или другому конкретному поставщику) предложить бинарную версию файла *.config, которая устанавливается в структуру GAC вместе с новейшей версией соответствующе-то компоновочного блока. Преимущество такого подхода в том, что тогда отпадает необходимость в наличии специальных файлов *.config в каталогах приложений клиента. Среда CLR читает текущий манифест и пытается найти запрошенную версию в структуре GAC. Но если при этом среда CLR обнаруживает файл политики публикации, читаются встроенные в этот файл XML-данные и выполняется соответствующее перенаправление на уровне GAC.
Файлы политики публикации создаются средствами командной строки с помощью .NET-утилиты al.exe (это редактор связей компоновочного блока). Этот инструмент имеет очень много опций, но для построения файла политики публикации потребуются указать только следующие данные:
• информацию о размещении файла *.config или *.xml, содержащего инструкции перенаправления;
• имя файла, задающего новые параметры политики публикации;
• информацию о размещении файла *.snk, используемого для создания подписи файла политики публикации;
• номера версии, назначаемой создаваемому файлу политики публикации.
Чтобы построить файл политики публикации, контролирующий библиотеку CarLibrary.dll, нужно использовать следующую команду.
al /link: CarLibraryPolicy.xml /out:policy.1.0.CarLibrary.dll /keyf: C:MyKeymyKey.snk /v:1.0.0.0
Здесь XML-содержимое включено в файл с именем CarLibraryPolicy.xml. Имя выходного файла, которое должно иметь формат policy.‹главный(номер версии)›. ‹дополнителъный(номер версии)›.конфигурируемыйКомпоновочныйБлок), указывается с помощью флага /out. Обратите также внимание на то, что имя файла, содержащего значения открытого и секретного ключей, тоже должно быть представлено, но с помощью опции /keyf. (Поскольку файлы политики публикации являются общедоступными, они должны быть строго именованными.)
В результате использования al.exe вы получите новый компоновочный блок, который можно разместить в структуре GAC для того, чтобы, не используя отдельные файлы конфигурации для каждого приложения, "заставить" все клиенты использовать CarLibrary.dll версии 2.0.0.0.
Игнорирование файла политики публикации
Теперь предположим, что вы (как администратор системы) установили файл политики публикации (и новую, более позднюю версию компоновочного блока) на машине клиента. Как обычно и случается, девять из десяти соответствующих приложений перешли к использованию версии 2.0.0.0 без всяких ошибок. Однако в одном из приложений клиента при доступе к CarLibrary.dll версии 2.0.0.0 возникли проблемы (мы с вами знаем, что создать программное обеспечение, которое будет демонстрировать 100%-ную обратную совместимость, практически невозможно).
В таком случае можно построить файл конфигурации для данного "проблемного" клиента с инструкциями, которые позволят среде CLR игнорировать установленные в GAC файлы политики публикации. При этом другие приложения клиента, которые могут использовать новый компоновочный блок .NET, с помощью установленного файла политики публикации будут перенаправлены на новый компоновочный блок. Чтобы отключить политику публикации для отдельного клиента, создайте файл *.сonfig (с подходящим именем), в котором рамках элемента ‹publisherPolicy› установите для атрибута apply значение no. После этого среда CLR будет загружать компоновочный блок той версии, которая указана в манифесте клиента.
‹configuratоn›
‹runtime›
‹assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"›
‹publisherPolicy apply="no" /›
‹/assemblуВinding›
‹/runtime›
‹/configuration›
Элемент ‹codeBase›
Файлы конфигурации приложения могут также указать базовый программный код. С помощью элемента ‹codeBase› можно дать инструкцию среде CLR искать зависимые компоновочные блоки в указанных местах (например, в общей сетевой папке или в локальном каталоге вне каталога приложения клиента).
Замечание. Если значение, присвоенное в рамках элемента ‹codeBase›, указывает на удаленную машину, компоновочный блок будет загружен по требованию в специальный каталог структуры GAC, имеющий специальное название – кэш загрузки. Увидеть содержимое кэша загрузки можно с помощью gacutil.exe, указав при запуске этой утилиты опцию /ldl.
С учетом того, что вы уже знаете об установке компоновочных блоков в GAC, будет ясно, что компоновочные блоки, загружаемые с помощью элемента ‹codeBase›, должны быть строго именованными (в конце концов, как же иначе среда CLR смогла бы установить удаленные компоновочные блоки в структуру GAC?).
Замечание. Строго говоря, элемент ‹codeBase› можно использовать и для зондирования компоновочных блоков, которые не являются строго именованными. Однако в таком случае адрес компоновочного блока должен задаваться относительно каталога приложения клиента (в этом отношении данный элемент предлагает более широкие возможности, чем элемент ‹privatePath›).
Создайте консольное приложение с именем СodeBaseСlient, установите для него ссылку на CarLibrary.dll версии 2.0.0.0 и измените исходный файл так.
using CarLibrary;
namespace CodeBaseClient {
class Program {
static void Main(string[] args) {
Console.WriteLine("***** Забавы с CodeBase *****");
SportsCar с = new SportsCar();
Console.WriteLine("Создана спортивная машина.");