readme.md
99 lines
| 6.2 KiB
| text/x-minidsrc
|
MarkdownLexer
cin
|
r276 | # XML Конфигурация IoC контейнера | |
Данная библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования | |||
контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом. | |||
На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/) | |||
Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека позволяет решать следующие задачи | |||
- Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения | |||
- Включение существующе конфигурации `<include href='config.xml'/>` в текущую | |||
- Поддержка сериализованных объектов в качестве регистраций сервисов и параметров | |||
- Описание зависимостей может быть расширено собсвтенными элементами с произвольной структурой | |||
- Поддержка специфиакции генериков любой вложенности `Dictionary{Foo,Bar{Int32}}` | |||
## Общая архитектура | |||
`Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру, в частности к Unity. | |||
1. Настраивается схема `ContainerConfigurationSchema` | |||
2. Загружается документ и десереализуется в виде `ContainerElement` | |||
3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` | |||
`ContainerConfigurationSchema` - определяет элементы которые могут быть использованы в конфигурации контейнера, предоставляет настроенный `XmlSerializer`. | |||
`ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, добавляет записи регистрации сервисов. | |||
`ContainerElement` - Корневой элемент конфигурации, который загружается из документа. | |||
Классы заканчивающиеся словом `Builder` используются для применения конфигурации к контейнеру, | |||
классы заканчивающиеся на `Element` содержат информацию о конфигурации и десериализуются из исходного документа. | |||
## Структура конфигурации контейнера | |||
Элемент верхнего уровня всегда `ContainerElemnt`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`. | |||
Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`, | |||
который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия. | |||
Примерами элементов контейнера могут быть | |||
- `<include href='config.xml'/>` - включение конфигурации из указанного места | |||
- `<namespace name='My.App'/>` - добавление пространства имен для поиска типов | |||
- `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1`` | |||
Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`, | |||
разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме. | |||
Например, мы используем компоненту `MyHttpClient` для загрузки данных | |||
```xml | |||
<register type="IClient" mapTo="MyHttpClient"> | |||
<property name="proxy"> | |||
<value>socks5://proxy1.my.company</value> | |||
</property> | |||
</register> | |||
``` | |||
При частом использовании можно сделать описание конфигурации несколько проще, | |||
описав новый эелемент конфигурации | |||
```csharp | |||
public class MyHttpClientElement : ContainerItemElement { | |||
public string Proxy { get; set; } | |||
public override void Visit(ContainerBuilder builder) { | |||
// создаем описание элемента | |||
var registration = new RegistrationElement { | |||
RegistrationType = "IClient", | |||
ImplementationType = "My.App.MyHttpClient", | |||
Injectors = new [] { | |||
new PropertyInjectionElement { | |||
Name = "Proxy", | |||
Value = ValueParameterElement { | |||
Value = Proxy | |||
} | |||
} | |||
} | |||
}; | |||
// применяем созданное описание к контейнеру | |||
builder.Visit(registration) | |||
} | |||
} | |||
``` | |||
Регистрируем новый элемент в схеме | |||
```csharp | |||
schema.RegisterContainerElement<MyHttpClientElement>("http"); | |||
``` | |||
Используем новый элемент в конфигурации | |||
```xml | |||
<http> | |||
<proxy>socks5://proxy1.my.company</propxy> | |||
</http> | |||
``` |