##// END OF EJS Templates
code cleanup and refactoring
code cleanup and refactoring

File last commit:

r281:e0916ddc9950 v3
r281:e0916ddc9950 v3
Show More
XmlConfiguration.md
112 lines | 7.2 KiB | text/x-minidsrc | MarkdownLexer

XML Конфигурация IoC контейнера

Библиоетка создавалась для загрузки и применения конфигурации к IoC контейнеру, она не предназначена для конфигурирования контейнера во время выполнения, большинство контейнеров уже обладают данным функционалом.

На данный момент поддерживается единственный вид контейнера - Unity Container

Unity уже обладает средствами загрузки конфигурации из XML, данная библиотека реализует аналогичный функционал, кроме того, позволяет решать следующие задачи:

  • Конфигурация является простым Xml документом, который можно получить из любого источика и не ограничивается .config файлами приложения
  • Включение существующе конфигурации <include href='config.xml'/> в текущую
  • Поддержка сериализованных объектов в качестве регистраций сервисов и параметров
  • Поддержка специфиакции генериков любой вложенности, например Dictionary{Foo,Bar{Int32}}
  • Поддержка фабрик в XML конфигурации
  • Расширение схемы XML конфигурации собственными элементами

Общая архитектура

Пространство имен Implab.ServiceHost.Unity содержит в себе классы для загрузки и применения XML конфигурации к IoC контейнеру.

Применение конфигурации к контейнеру состоит из следующих основных шагов:

  1. Настраивается схема ContainerConfigurationSchema XML конфигурации контейнера
  2. Загружается документ и десереализуется в виде ContainerElement
  3. Создается ContainerBuilder при помощи которого применяются настройки из ContainerElement к контейнеру

Схема ContainerConfigurationSchema определяет элементы документа, которые могут быть использованы в конфигурации контейнера, позволяет создать XmlSerializer, который используется для загрузки конфигурации.

ContainerBuilder - основной класс, который используется для применения конфигурации к контейнеру, он добавляет записи регистрации сервисов из конфигурации в контейнер.

ContainerElement - Конфигурация контейнера, которая загружается из документа, состоит из директив для ContainerBuilder, а также из записей регистрации сервисов.

В библиотеки приняты следующие правила именования классов:

  • ***Builder используются для применения конфигурации к контейнеру,
  • ***Element содержат информацию о конфигурации и десериализуются из исходного документа.

Структура конфигурации контейнера

Элемент верхнего уровня всегда container, он используется для хранения набора элеметов, которые распознаются и выполняются ContainerBuilder.

Все элементы, входящие в контейнер наследуются от абстрактного класса ContainerItemElement, который позволяет получить текущий ContainerBuilder и выполнить над ним какие-либо действия.

Основные элементы конфигурации контенейра

  • <include href='config.xml'/> - включение конфигурации из указанного места
  • <namespace name='My.App'/> - добавление пространства имен для поиска типов
  • <register type='MyGenericType{}'/> - добавление в контейнер регистрации типа My.App.MyGenericType`1
  • <factory type='IFactory{Foo}' mapTo ='MyFactory'/> - фабрика, регистрирует свой тип, а также тип Foo
  • <serialized /> - сериализованный экземпляр объекта, использует XmlSerializer для десериализации
  • <value /> - значение объекта в виде строки, используется для простых типов

Полный набор элементов, доступных для использования в контейнере определяет схема ContainerConfigurationSchema, разработчик может расширить контейнер совими собственными элементами зарегистрировав их в схеме.

register

О

Например, мы используем компоненту MyHttpClient для загрузки данных

    <register type="IClient" mapTo="MyHttpClient">
        <property name="proxy">
            <value>socks5://proxy1.my.company</value>
        </property>
    </register>

При частом использовании можно сделать описание конфигурации несколько проще, описав новый эелемент конфигурации

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)
    }
}

Регистрируем новый элемент в схеме

schema.RegisterContainerElement<MyHttpClientElement>("http");

Используем новый элемент в конфигурации

    <http>
        <proxy>socks5://proxy1.my.company</propxy>
    </http>