276
+ − 1 # XML Конфигурация IoC контейнера
+ − 2
281
+ − 3 Библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования
276
+ − 4 контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом.
+ − 5
+ − 6 На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/)
+ − 7
281
+ − 8 Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека реализует аналогичный функционал, кроме того, позволяет решать следующие задачи:
276
+ − 9
+ − 10 - Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения
+ − 11 - Включение существующе конфигурации `<include href='config.xml'/>` в текущую
+ − 12 - Поддержка сериализованных объектов в качестве регистраций сервисов и параметров
281
+ − 13 - Поддержка специфиакции генериков любой вложенности, например `Dictionary{Foo,Bar{Int32}}`
+ − 14 - Поддержка фабрик в XML конфигурации
+ − 15 - Расширение схемы XML конфигурации собственными элементами
276
+ − 16
+ − 17 ## Общая архитектура
+ − 18
281
+ − 19 Пространство имен `Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру.
+ − 20
+ − 21 Применение конфигурации к контейнеру состоит из следующих основных шагов:
276
+ − 22
281
+ − 23 1. Настраивается схема `ContainerConfigurationSchema` XML конфигурации контейнера
276
+ − 24 2. Загружается документ и десереализуется в виде `ContainerElement`
281
+ − 25 3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` к контейнеру
276
+ − 26
281
+ − 27 Схема `ContainerConfigurationSchema` определяет элементы документа, которые могут быть использованы в конфигурации контейнера, позволяет создать `XmlSerializer`, который используется для загрузки конфигурации.
276
+ − 28
281
+ − 29 `ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, он добавляет записи регистрации сервисов из конфигурации в контейнер.
276
+ − 30
281
+ − 31 `ContainerElement` - Конфигурация контейнера, которая загружается из документа, состоит из директив для `ContainerBuilder`, а также из записей регистрации сервисов.
276
+ − 32
281
+ − 33 В библиотеки приняты следующие правила именования классов:
+ − 34
+ − 35 - `***Builder` используются для применения конфигурации к контейнеру,
+ − 36 - `***Element` содержат информацию о конфигурации и десериализуются из исходного документа.
276
+ − 37
+ − 38 ## Структура конфигурации контейнера
+ − 39
281
+ − 40 Элемент верхнего уровня всегда `container`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`.
276
+ − 41
+ − 42 Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`,
+ − 43 который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия.
+ − 44
281
+ − 45 Основные элементы конфигурации контенейра
276
+ − 46
+ − 47 - `<include href='config.xml'/>` - включение конфигурации из указанного места
+ − 48 - `<namespace name='My.App'/>` - добавление пространства имен для поиска типов
+ − 49 - `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1``
281
+ − 50 - `<factory type='IFactory{Foo}' mapTo ='MyFactory'/>` - фабрика, регистрирует свой тип, а также тип `Foo`
+ − 51 - `<serialized />` - сериализованный экземпляр объекта, использует `XmlSerializer` для десериализации
+ − 52 - `<value />` - значение объекта в виде строки, используется для простых типов
276
+ − 53
+ − 54 Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`,
+ − 55 разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме.
+ − 56
281
+ − 57 ### register
+ − 58
+ − 59 О
+ − 60
+ − 61
276
+ − 62 Например, мы используем компоненту `MyHttpClient` для загрузки данных
+ − 63
+ − 64 ```xml
+ − 65 <register type="IClient" mapTo="MyHttpClient">
+ − 66 <property name="proxy">
+ − 67 <value>socks5://proxy1.my.company</value>
+ − 68 </property>
+ − 69 </register>
+ − 70 ```
+ − 71
+ − 72 При частом использовании можно сделать описание конфигурации несколько проще,
+ − 73 описав новый эелемент конфигурации
+ − 74
+ − 75 ```csharp
+ − 76 public class MyHttpClientElement : ContainerItemElement {
+ − 77
+ − 78 public string Proxy { get; set; }
+ − 79
+ − 80 public override void Visit(ContainerBuilder builder) {
+ − 81 // создаем описание элемента
+ − 82 var registration = new RegistrationElement {
+ − 83 RegistrationType = "IClient",
+ − 84 ImplementationType = "My.App.MyHttpClient",
+ − 85 Injectors = new [] {
+ − 86 new PropertyInjectionElement {
+ − 87 Name = "Proxy",
+ − 88 Value = ValueParameterElement {
+ − 89 Value = Proxy
+ − 90 }
+ − 91 }
+ − 92 }
+ − 93 };
+ − 94
+ − 95 // применяем созданное описание к контейнеру
+ − 96 builder.Visit(registration)
+ − 97 }
+ − 98 }
+ − 99 ```
+ − 100
+ − 101 Регистрируем новый элемент в схеме
+ − 102
+ − 103 ```csharp
+ − 104 schema.RegisterContainerElement<MyHttpClientElement>("http");
+ − 105 ```
+ − 106
+ − 107 Используем новый элемент в конфигурации
+ − 108
+ − 109 ```xml
+ − 110 <http>
+ − 111 <proxy>socks5://proxy1.my.company</propxy>
+ − 112 </http>
+ − 113 ```