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