Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции OOP c#.doc
Скачиваний:
44
Добавлен:
22.09.2019
Размер:
3.38 Mб
Скачать

2.14. Конфигурирование сборок

Необходимость конфигурирования сборок обычно возникает при развертывании приложений. Платформа .NET предлагает стандартизированный подход к конфигурированию, основанный на использовании конфигурационных XML-файлов. Специальное пространство имен System.Configuration отвечает за работу с файлами конфигураций.

Рассмотрим общую схему файла конфигурации. Корневым элементом файла всегда является элемент configuration. Некоторые подчиненные элементы описаны далее:

  • startup – совокупность параметров запуска приложения;

  • runtime – параметры времени выполнения. Они регулируют способ загрузки сборок и сборку мусора;

  • system.runtime.remoting – параметры конфигурирования, необходимые для настройки механизма .NET Remoting;

  • system.diagnostics – совокупность диагностических параметров, которые задает способ отладки приложений, перенаправляют сообщения отладки и т. д.;

  • system.web – параметры конфигурации приложений ASP.NET.

Платформа .NET Framework имеет один файл конфигурации компьютера с параметрами, относящимися к системе в целом. Этот файл называется machine.config. Любая сборка может иметь собственный конфигурационный файл. Он должен носить имя файла сборки (с расширением) с добавленным окончанием .config и располагаться в одном каталоге со сборкой. Таким образом, файл конфигурации для main.exe должен называться main.exe.config. В случае web-приложений файл конфигурации всегда называется web.config.

Разберем на примерах некоторые возможности конфигурирования. Рассмотрим подробнее структуру секции runtime:

<configuration>

<runtime>

<developmenMode>

<assemblyBinding>

<probing>

<publisherPolicy>

<qualifyAssembly>

<dependentAssembly>

<assemblyIdentity>

<bindingRedirect>

<codeBase>

<publisherPolicy>

<gcConcurrent>

<developmenMode>

Прототип тэга:

<developmenMode developerInstallation = "true" | "false"/>

Если параметр тэга равен "true", то среда исполнения помимо обычных каталогов пытается искать сборки в каталогах, указанных в переменной среды окружения DEVPATH.

<assemblyBinding>

Тэг служит для объединения группы вложенных элементов

<probing>

Прототип тэга:

<probing privatePath = "paths"/>

Тэг используется для указания подкаталогов, в которых производится поиск локальных сборок приложения. Например, пусть основное приложение AppMain.exe размещено в каталоге C:\Test, и оно использует сборку Add1.dll из каталога C:\Test\bin и сборку Add2.dll из каталога C:\Test\bin\bin2. Тогда для корректного запуска основного приложения файл AppMain.exe.config должен иметь следующий вид:

<configuration>

<runtime>

<assemblyBinding>

<probing privatePath = "bin;bin\bin2"/>

</assemblyBinding>

</runtime>

</configuration>

<publisherPolicy>

Прототип тэга:

<publisherPolicy apply = "yes" | "no"/>

Пусть приложение использует некую стороннюю библиотеку. Если в тэге <publisherPolicy> определен параметр "yes" (по умолчанию), то при установке новой версии библиотеки, приложение автоматически будет использовать эту новую версию. В случае параметра "no" приложение откажется работать с новой версией.

<qualifyAssembly>

Прототип тэга:

<qualifyAssembly partialName="PartName" fullName="FullName"/>

Этот тэг позволяет ассоциировать сокращенное имя сборки с полным строгим именем для удобства использования в программе. Рассмотрим следующий пример:

<configuration>

<runtime>

<assemblyBinding>

<qualifyAssembly

partialName = "Strong"

fullName = "Strong, version=1.2.0.0,

culture=neutral,

publicKeyToken=1234567812345678"/>

</assemblyBinding>

</runtime>

</configuration>

Конфигурационный файл данного примера позволит везде в программе вместо длинного строго имени использовать короткий псевдоним Strong.

<dependentAssembly>

Этот тэг позволяет настроить загрузку персонально для каждой сборки, связанной с основным приложением. Он сам является пустым и объединяет элементы <assemblyIdentity>, <bindingRedirect>, <codeBase>, <publisherPolicy>. Элемент должен быть указан для каждой сборки, политику загрузки которой мы собираемся настраивать.

<assemblyIdentity>

Прототип тэга:

<assemblyIdentity

name = "assembly Name" publicKeyToken = "public key token"

culture = "assembly culture"/>

Тэг идентифицирует сборку

<bindingRedirect>

Прототип тэга:

<bindingRedirect

old version = "old assembly version"

new version = "new assembly version"/>

Тэг позволяет подменить версию сборки, которая будет загружаться приложением. Рассмотрим пример:

<configuration>

<runtime>

<assemblyBinding>

<dependentAssembly>

<assemblyIdentity name = "myAssembly"

publicKeyToken="32ab4ba45e0a69a1"

culture = "neutral"/>

<bindingRedirect oldVersion = "1.0.0.0"

newVersion = "2.0.0.0"/>

</dependentAssembly>

</assemblyBinding>

</runtime>

</configuration>

Теперь, если основное приложение запросит сборку myAssembly версии 1.0.0.0, то, ничего не зная об этом, получит сборку версии 2.0.0.0.

<codeBase>

Прототип тэга:

<codeBase version="assembly version" href="URL of assembly"/>

Этот тэг позволяет задать произвольное местоположение зависимой сборки. Причем, в качестве параметра href может быть указан сетевой адрес. Продемонстрируем это на примере:

<configuration>

<runtime>

<assemblyBinding>

<dependentAssembly>

<assemblyIdentity name = "myAssembly"

publicKeyToken = "32ab4ba45e0a69a1"

culture = "neutral"/>

<codeBase version = "1.0.0.0"

href = "http://localhost/one/Strong.dll"/>

</dependentAssembly>

</assemblyBinding>

</runtime>

</configuration>

Этот конфигурационный файл предписывает загружать среде исполнения сборку Strong из Интернета по адресу http://localhost/one/Strong.dll.

<gcConcurrent>

Прототип тэга:

<gcConcurrent enabled = "true" | "false"/>

Если параметр enabled установлен в true, то «сборка мусора» происходит в параллельном потоке по отношению к основному приложению. Это поведение по умолчанию.

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

  • <add key = "name" value = "the value"/> – добавляет новый ключ и значение в коллекцию конфигурационных элементов;

  • <remove key = "name"/> – удаляет существующий ключ и значение из коллекции конфигурационных элементов;

  • <clear/> – очищает коллекцию конфигурационных элементов.

Для работы с данными секции appSettings используется класс ConfigurationSettings из пространства имен Sistem.Configuration. Статическое свойство AppSettings представляет собой коллекцию, позволяющую получить строковое значение конфигурационного элемента по ключу.

Пусть имеется следующее консольное приложение main.exe:

using System;

using System.Configuration;

class MainClass {

static void Main() {

string v1 = ConfigurationSettings.AppSettings["key1"];

string v2 = ConfigurationSettings.AppSettings["key2"];

Console.WriteLine(v1);

Console.WriteLine(v2);

Console.ReadLine();

}

}

Создадим для этого приложения конфигурационный файл main.exe.config:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<appSettings>

<add key="key1" value="Alex" />

<add key="key2" value="Volosevich" />

</appSettings>

</configuration>

Результат выполнения main.exe:

Alex

Volosevich

Все секции конфигурационного файла разбираются специальными классами-обработчиками (section handlers). Такой класс реализует интерфейс System.Configuration.IConfigurationSectionHandler. В составе .NET Framework имеется несколько готовых классов-обработчиков: NameValueSectionHandler, IgnoreSectionHandler, DictionarySectionHandler, SingleTagSectionHandler.

Чтобы описать в конфигурационном файле собственную секцию, следует использовать тэг configSections. Вложенные элементы section данного тэга имеют атрибут name – имя секции, и атрибут type – полное имя класса-обработчика. Рассмотрим следующий пример конфигурационного файла:

<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<configSections>

<section name = "mySection"

type = "System.Configuration.NameValueSectionHandler" />

</configSections>

<mySection>

<add key="key1" value="Alex" />

<add key="key2" value="Volosevich" />

</mySection>

</configuration>

Этот файл задает пользовательскую секцию с именем mySection и указывает, что для ее обработки следует использовать NameValueSectionHandler, то есть, содержимое секции будет доступно как NameValueCollection.

Для чтения информации из пользовательской секции применяется метод ConfigurationSettings.GetConfig(). В качестве параметра методу передается имя секции. Метод возвращает значение типа object, которое следует привести к типу класса-обработчика секции. Следующее приложение читает информацию из своего (описанного выше) конфигурационного файла:

using System;

using System.Configuration;

using System.Collections.Specialized;

class CustomConfig {

static void Main() {

NameValueCollection nvc =

(NameValueCollection)ConfigurationSettings.GetConfig("mySection");

Console.WriteLine(nvc["key1"]);

Console.WriteLine(nvc["key2"]);

}

}

Следует иметь в виду, что файл конфигурации читается и разбирается исполняемой средой один раз, при загрузке приложения. Поэтому все изменения, которые внесены в этот файл, не буду иметь эффекта до перезагрузки приложения. Если такое поведение является неприемлемым, то можно воспользоваться классом System.IO.FileSystemWatcher. Как следует из его названия, класс позволяет отследить изменения, происходящие с файлом (или несколькими файлами). Подробности работы с классом FileSystemWatcher можно найти в .NET Framework SDK.