XmlConfiguration.md
112 lines
| 7.2 KiB
| text/x-minidsrc
|
MarkdownLexer
cin
|
r277 | # XML Конфигурация IoC контейнера | |
cin
|
r281 | Библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования | |
cin
|
r277 | контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом. | |
На данный момент поддерживается единственный вид контейнера - [Unity Container](https://unitycontainer.github.io/) | |||
cin
|
r281 | Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека реализует аналогичный функционал, кроме того, позволяет решать следующие задачи: | |
cin
|
r277 | ||
- Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается `.config` файлами приложения | |||
- Включение существующе конфигурации `<include href='config.xml'/>` в текущую | |||
- Поддержка сериализованных объектов в качестве регистраций сервисов и параметров | |||
cin
|
r281 | - Поддержка специфиакции генериков любой вложенности, например `Dictionary{Foo,Bar{Int32}}` | |
- Поддержка фабрик в XML конфигурации | |||
- Расширение схемы XML конфигурации собственными элементами | |||
cin
|
r277 | ||
## Общая архитектура | |||
cin
|
r281 | Пространство имен `Implab.ServiceHost.Unity` содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру. | |
Применение конфигурации к контейнеру состоит из следующих основных шагов: | |||
cin
|
r277 | ||
cin
|
r281 | 1. Настраивается схема `ContainerConfigurationSchema` XML конфигурации контейнера | |
cin
|
r277 | 2. Загружается документ и десереализуется в виде `ContainerElement` | |
cin
|
r281 | 3. Создается `ContainerBuilder` при помощи которого применяются настройки из `ContainerElement` к контейнеру | |
cin
|
r277 | ||
cin
|
r281 | Схема `ContainerConfigurationSchema` определяет элементы документа, которые могут быть использованы в конфигурации контейнера, позволяет создать `XmlSerializer`, который используется для загрузки конфигурации. | |
cin
|
r277 | ||
cin
|
r281 | `ContainerBuilder` - основной класс, который используется для применения конфигурации к контейнеру, он добавляет записи регистрации сервисов из конфигурации в контейнер. | |
cin
|
r277 | ||
cin
|
r281 | `ContainerElement` - Конфигурация контейнера, которая загружается из документа, состоит из директив для `ContainerBuilder`, а также из записей регистрации сервисов. | |
cin
|
r277 | ||
cin
|
r281 | В библиотеки приняты следующие правила именования классов: | |
- `***Builder` используются для применения конфигурации к контейнеру, | |||
- `***Element` содержат информацию о конфигурации и десериализуются из исходного документа. | |||
cin
|
r277 | ||
## Структура конфигурации контейнера | |||
cin
|
r281 | Элемент верхнего уровня всегда `container`, он используется для хранения набора элеметов, которые распознаются и выполняются `ContainerBuilder`. | |
cin
|
r277 | ||
Все элементы, входящие в контейнер наследуются от абстрактного класса `ContainerItemElement`, | |||
который позволяет получить текущий `ContainerBuilder` и выполнить над ним какие-либо действия. | |||
cin
|
r281 | Основные элементы конфигурации контенейра | |
cin
|
r277 | ||
- `<include href='config.xml'/>` - включение конфигурации из указанного места | |||
- `<namespace name='My.App'/>` - добавление пространства имен для поиска типов | |||
- `<register type='MyGenericType{}'/>` - добавление в контейнер регистрации типа ``My.App.MyGenericType`1`` | |||
cin
|
r281 | - `<factory type='IFactory{Foo}' mapTo ='MyFactory'/>` - фабрика, регистрирует свой тип, а также тип `Foo` | |
- `<serialized />` - сериализованный экземпляр объекта, использует `XmlSerializer` для десериализации | |||
- `<value />` - значение объекта в виде строки, используется для простых типов | |||
cin
|
r277 | ||
Полный набор элементов, доступных для использования в контейнере определяет схема `ContainerConfigurationSchema`, | |||
разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме. | |||
cin
|
r281 | ### register | |
О | |||
cin
|
r277 | Например, мы используем компоненту `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> | |||
``` |