Студопедия

Главная страница Случайная страница

Разделы сайта

АвтомобилиАстрономияБиологияГеографияДом и садДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеталлургияМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРелигияРиторикаСоциологияСпортСтроительствоТехнологияТуризмФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника






Состав и взаимодействие сборок






В платформе.NET сборка (assembly) – это единица развёртывания и контроля версий. Сборка состоит из одного или нескольких программных модулей и, возможно, данных ресурсов. Программный модуль содержит метаданные и код на Common Intermediate Language. Метаданные – это информационные таблицы с полным описанием всех типов, которые размещены в модуле или на которые ссылается модуль. В одном из модулей метаданные хранят манифест с описанием всех файлов сборки. Будем называть сборку однофайловой, если она состоит из одного файла. Иначе сборка называется многофайловой. Тот файл, который содержит манифест сборки, будем называть главным файлом сборки. На рис. 7 показана однофайловая сборка OneFile.exe, которая ссылается на многофайловую сборку ManyFiles.dll.

Рис. 7. Однофайловая и многофайловая сборки.

Простые приложения обычно представлены однофайловыми сборками. При разработке сложных приложений переход к многофайловым сборкам даёт следующие преимущества:

– ресурсы (текстовые строки, изображения и т. п.) можно хранить отдельно от исполняемого кода, что позволяет изменять ресурсы без перекомпиляции приложения;

– если исполняемый код приложения разделён на несколько модулей, то модули загружаются в память только по мере надобности;

– скомпилированный модуль может использоваться в нескольких сборках.

Рассмотрим пример создания и использования многофайловой сборки[20]. Пусть требуется построить консольное приложение, в котором функция Main() печатает на экране строку. Предположим, что эту строку возвращает статический метод GetText() класса TextClass.

public static class TextClass

{

public static string GetText()

{

return " message";

}

}

Файл TextClass.cs с исходным кодом класса TextClass скомпилируем в виде модуля (обратите внимание на ключ компилятора):

csc.exe /t: module TextClass.cs

После компиляции получим программный модуль TextClass.netmodule. Далее, создадим консольное приложение (файл MainClass.cs):

using System;

 

public class MainClass

{

public static void Main()

{

Console.Write(" Text from netmodule: ");

Console.WriteLine(TextClass.GetText());

}

}

Соберём многофайловую сборку. Ключ компилятора /addmodule позволяет добавить к сборке ссылку на внешний модуль. Этот ключ должен применяться для каждого подключаемого модуля.

csc.exe /addmodule: textclass.netmodule MainClass.cs

В итоге получим многофайловую сборку, состоящую из двух файлов: главного файла mainclass.exe и файла-модуля textclass.netmodule. Теперь можно создать новую сборку, в которой используется код из модуля textclass.netmodule, то есть сделать модуль разделяемым между несколькими сборками. Важное замечание: предполагается, что все файлы, составляющие нашу многофайловую сборку, размещены в одном каталоге.

Разберём вопрос взаимодействия сборок. Как правило, крупные программные проекты состоят из нескольких сборок, связанных ссылками. Среди этих сборок имеется некая основная (обычно оформленная как исполняемый файл), а другие сборки играют роль подключаемых библиотек с кодом необходимых типов (как правило, имеют расширение *.dll).

Представим пример, который будет использоваться в дальнейшем. Пусть имеется класс (в файле UL.cs), содержащий «полезную» функцию:

namespace UsefulLibrary

{

public class UsefulClass

{

public void Print()

{

System.Console.WriteLine(" Useful function");

}

}

}

Скомпилируем данный класс как библиотеку типов (расширение *.dll):

csc.exe /t: library UL.cs

Пусть основное приложение (файл main.cs) собирается использовать код из сборки UL.dll:

using System;

using UsefulLibrary;

 

public class MainClass

{

public static void Main()

{

// используем класс из другой сборки

UsefulClass a = new UsefulClass();

a.Print();

}

}

Ключ компилятора /r (или /reference) позволяет установить ссылку на требуемую сборку. Скомпилируем приложение main.cs:

csc.exe /r: UL.dll main.cs

В Visaul Studio для добавления ссылок на сборки используется ветвь References в дереве проекта в Solution Explorer, или команда меню Project | Add Reference.

Создавая сборку, программист может снабдить её цифровой подписью, версией, указанием на региональную принадлежность и другой информацией. Эти данные внедряются в сборку при помощи атрибутов уровня сборки. Атрибуты можно разместить в любом файле с исходным кодом, необходимо только подключить пространство имён System.Reflection. Если для разработки используется Visual Studio, все атрибуты уровня сборки по умолчанию находятся в файле AssemblyInfo.cs. Кроме этого, в Visual Studio удобно редактировать атрибуты не напрямую, а используя диалоговое окно свойств проекта.

Цифровая подпись защищает сборку от несанкционированного изменения. Платформа.NET использует для цифровой подписи алгоритм RSA. Схема подписания сборки показана на рис. 8.

Рис. 8. Подписание сборки.

Для того чтобы снабдить сборку цифровой подписью, необходим открытый ключ и закрытый ключ. Утилита sn.exe, входящая в состав.NET Framework SDK, способна сгенерировать файл с парой ключей:

sn.exe -k keys.snk

Чтобы подписать сборку, используется атрибут уровня сборки [AssemblyKeyFile] (имя файла с ключами нужно указать в качестве аргумента атрибута) или ключ компилятора командной строки /keyfile:

using System;

using System.Reflection;

 

[assembly: AssemblyKeyFile(" keys.snk")]

namespace UsefulLibrary {... }

Сгенерировать ключи и подписать сборку можно в Visual Studio в окне свойств проекта (закладка Signing).

Чтобы указать версию сборки, используется атрибут [AssemblyVersion]. Номер версии имеет формат Major.Minor.Build.Revision. Часть Major является обязательной. Любая другая часть может быть опущена (в этом случае она полагается равной нулю). Часть Revision можно задать как *, тогда компилятор генерирует её как количество секунд, прошедших с полуночи, делённое на два. Часть Build также можно задать как *. Тогда для неё будет использовано количество дней, прошедших с 1 февраля 2000 года.

using System;

using System.Reflection;

 

[assembly: AssemblyVersion(" 1.2.0.0")]

namespace UsefulLibrary {... }

Для задания региональной принадлежности используется атрибут уровня сборки [AssemblyCulture]. Для определения версии и региональной принадлежности можно использовать окно свойств проекта в Visual Studio (закладка Application, кнопка Assembly Information).

Платформа.NET разделяет сборки на локальные (или сборки со слабыми именами) и глобальные (или сборки с сильными именами). Если UL.dll рассматривается как локальная сборка, то при выполнении приложения она должна находиться в том же каталоге, что и main.exe[21]. Локальные сборки обеспечивают простоту развёртывания приложения (все его компоненты сосредоточены в одном месте) и изолированность компонентов. Имя локальной сборки – слабое имя – это имя файла сборки без расширения.

Хотя использование локальных сборок имеет свои преимущества, иногда необходимо сделать сборку общедоступной. До появления платформы.NET доминировал подход, при котором код общих библиотек помещался в системный каталог простым копированием фалов при установке. Такой подход привёл к проблеме, известной как «ад DLL» (DLL Hell). Инсталлируемое приложение могло заменить общую библиотеку новой версией, при этом другие приложения, ориентированные на старую версию библиотеки, переставали работать. Для устранения «ада DLL» в платформе.NET используется специальное защищённое хранилище сборок (Global Assembly Cache, GAC).

Сборки, помещаемые в GAC, должны удовлетворять определённым условиям. Во-первых, такие глобальные сборки должны иметь цифровую подпись. Это исключает подмену сборок злоумышленниками. Во-вторых, для глобальных сборок отслеживаются версии и языковые культуры. Допустимой является ситуация, когда в GAC находятся разные версии одной и той же сборки, используемые разными приложениями.

Сборка, помещённая в GAC, получает сильное имя. Как раз использование сильного имени является тем признаком, по которому среда исполнения понимает, что речь идёт не о локальной сборке, а о сборке из GAC. Сильное имя включает имя главного файла сборки (без расширения), версию сборки, указание о региональной принадлежности и маркер открытого ключа сборки:

Рассмотрим процесс создания сборки с сильным именем на примере сборки UL.dll. Во-первых, сборку необходимо снабдить цифровой подписью. После подписания для сборки можно указать версию и региональную принадлежность (это не обязательные действия). После этого сборку можно поместить в GAC. Простейший вариант – использовать утилиту gacutil.exe, входящую в состав.NET Framework SDK. При использовании ключа /i сборка помещается в GAC, а ключ /u удаляет сборку из GAC:

gacutil.exe /i UL.dll

Теперь сборка UL.dll помещена в GAC. Её сильное имя (для ссылки в программах) имеет вид:

UL, Version=1.2.0.0, Culture=neutral, PublicKeyToken=ff824814c57facfe






© 2023 :: MyLektsii.ru :: Мои Лекции
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.
Копирование текстов разрешено только с указанием индексируемой ссылки на источник.