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 ``` |