Поиск

Управление версиями сборок

Декларация сборки содержит номер версии и список всех сборок (и связанную с ними информацию о версиях), на которые ссылается эта сборка. Номера версий подразделяются на четыре сегмента и принимают вид:

<старшая версияхмладшая версия><компоновка><ревизия>

В период выполнения это работает так: на основе информации о номере версии .NET решает, какую версию данной сборки использовать с приложением. Как вы вскоре увидите, поведение по умолчанию — оно называется политикой управления версиями — заключается в следующем: после установки приложения .NET будет автоматически использовать самую последнюю версию сборок, на которые ссылается это приложение, если номера их старших и младших версий совпадают. Это поведение по умолчанию позволяют изменить файлы конфигурации.

Управление версиями относится только к совместно используемым сборкам (для закрытых сборок оно не требуется) и является, пожалуй, наиболее важным фактором, определяющим решение о создании совместно используемых сборок. Поэтому рассмотрим примеры, иллюстрирующие, как все это действует и как работать с версиями сборки.

Мой Код представляет собой упрощенный вариант примера управления версиями, поставляемого с .NET SDK. В него не входит материал Windows Forms, поскольку я хочу сосредоточиться на управлении версиями и действиях, осуществляемых для этого исполняющей средой.
У меня есть два исполняемых файла, представляющих два пакета бухгалтерского учета, — Personal и Business. Оба приложения обращаются к общей совместно используемой сборке Account. Класс Account может лишь сообщать свою версию, позволяя убедиться, что наши приложения обращаются именно к предназначенной для них версии класса Account. В этой связи в пример входят несколько версий класса Account, что поможет вам уяснить, как работает управление версиями при использовании политики по умолчанию и как с помощью XML устанавливается связь между приложением и конкретной версией сборки.

Для начала создайте папку Accounting, а в ней — пару ключей, которые будут использованы всеми версиями класса Account. Для этого в командной строке папки Accounting наберите:

sn /k account.key
Создайте в папке Accounting еще одну папку —
Personal, а в ней — файл Personal.cs:
// Accounting\Personal\Personal.cs using System;
class PersonalAccounting {
public static void Main() {
Console.WriteLine
("PersonalAccounting calling Account.PrintVersion");
Account. PrintVersionO; } -}

В папке Personal создайте папку Account 1000, где будет располагаться первая версия класса Account нашего примера. Затем в папке Account 1000 создайте файл Account.cs:

// Accounting\Personal\Account1000\Account.cs
using System;
using System.Reflection;
[assembly:AssemblyKeyFile("..\. .\Account.key")]
[assembly:AssemblyVersion("1.0.0.0")] public class Account <
public static void PrintVersionO
{
Console.WriteLine
("This is version 1.0.0.0 of the Account class"); >
}

Как видите, я использую атрибуты AssemblyeKeyFile и Assembly Version, чтобы указать компилятору С# ранее созданную пару ключей и явно задать версию класса Account. Теперь скомпонуйте DLL Account:
esc /t:library account.cs

Созданный класс Account нужно добавить к глобальному кэшу сборки: gacutil -i Account.dll
Если хотите, можете проверить, что сборка Account находится в кэше сборки. Теперь перейдите в папку Personal и скомпонуйте приложение, например, так:

esc Personal.cs /r:Account1000\Account.dll

При запуске этого приложения получится следующий результат:

PersonalAccounting calling Account.PrintVersion This
is version 1.0.0.0 of the Account class

До сих пор мы не сделали ничего нового. Но посмотрим, что произойдет при установке еще одного приложения, использующего более новую версию класса Account.
Создайте в папке Accounting папку Business, а в ней — папку Ассо-untlOOl для представления новой версии класса Account. Этот класс находится в файле Account.cs и выглядит почти идентично предыдущей версии.

// Accounting\Business\Account10Q1\Account,cs
using System;
using System.Reflection;
[assembly:AssemblyKeyFile("..\..\Account.key")]
[assembly:AssemblyVersion("1.0.0.1")] public class Account
{
public static void PrintVersionQ {
Console.WriteLine
("This is version 1.0.0.1 of the Account class"); } }

Как и прежде, скомпонуйте эту версию класса Account командами: esc /t:library Account, cs gacutil -i Account.dll
На этом этапе вы должны видеть в глобальном кэше сборки две версии класса Account. Теперь создайте (в папке Accounting\Business) файл Business, cs:

// Accounting\Business\Business.cs using System;
class PersonalAccounting {
public static void Main() {
Console.WriteLine
("BusinessAccounting calling Account.PrintVersion"); Account. PrintVersionO; } }

Скомпонуйте приложение Business командой: esc business.cs /r:Account1001\Account.dll
Запуск этого приложения даст следующие результаты. Это подтверждает тот факт, что приложение Business использует версию 1.0.0.1 сборки Account.

BusinessAccounting calling Account.PrintVersion This is version 1.0.0.1 of the Account class
А теперь запустите приложение Personal и посмотрите, что происходит! PersonalAccounting calling Account.PrintVersion This is version 1.0.0.1 of the Account class

Оба приложения, Personal и Business, обращаются к последней версии сборки Account*. Почему? Так все и должно быть при использовании подхода QFE (Quick Fix Engineering) и политики управления версиями .NET по умолчанию.