Главная страница
Навигация по странице:

  • Что находится в загруженном файле Zip-файл, который содержит все вам необходимое: скомпилированные бинарные файлы, исходный код и документацию. Какие платформы поддерживаются

  • Сколько он стоит Нисколько. Это программное обеспечение с открытым исходным кодом. Откуда мне получить помощь

  • Spring.NET основана данная глава

  • Внедрение зависимостей в. Внедрение зависимостей в .NET. Руководство по применению этого механизма. Net приложениях. Книга демонстрирует основные паттерны на обычном языке C#, поэтому вы в полной мере поймете, как работает механизм внедрения зависимостей


    Скачать 5.66 Mb.
    НазваниеРуководство по применению этого механизма. Net приложениях. Книга демонстрирует основные паттерны на обычном языке C#, поэтому вы в полной мере поймете, как работает механизм внедрения зависимостей
    АнкорВнедрение зависимостей в .net
    Дата14.12.2019
    Размер5.66 Mb.
    Формат файлаpdf
    Имя файлаВнедрение зависимостей в .NET.pdf
    ТипРуководство
    #100226
    страница32 из 43
    1   ...   28   29   30   31   32   33   34   35   ...   43
    Откуда мне его получить?
    Перейти на страницу www.sprin gframework.net/do wnload.htm l и загрузить последний релиз.
    Из Visual Studio 2010 можно получить его посредством NuGet. Имя пакета – Spring.Core. Но если вам нужны возможности механизма перехвата, то в этом случае вам нужен пакет Spring.Aop.

    Что находится в загруженном файле?
    Zip-файл, который содержит все вам необходимое: скомпилированные бинарные файлы, исходный код и документацию.

    Какие платформы поддерживаются?
    Поддерживаются все версии ASP.NET, начиная с .NET 1.1, хотя последующие версии будут поддерживать только версии .NET 2.0 и выше.

    Сколько он стоит?
    Нисколько. Это программное обеспечение с открытым исходным кодом.

    Откуда мне получить помощь?
    Коммерческую поддержку можно получить от SpringSource – организация, которая занимается разработкой Spring.NET .
    Невзирая на коммерческую поддержку, Spring.NET все еще остается программным обеспечением с открытым исходным кодом, которое обладает процветающей экосистемой, поэтому, скорее всего (но не гарантированно), помощь можно получить на официальном форуме http://forum.springframework.net
    На какой версии

    Spring.NET основана данная глава?
    1.3.1
    Использование DI-контейнера Spring.NET предполагает выполнение трех шагов, продемонстрированных на рисунке 12-2.

    457
    Рисунок 12-2: Полноценный паттерн применения Spring.NET включает в себя три шага: сначала мы задаем то, как объекты конфигурируются и компонуются в XML-файле. Затем мы загружаем XML-конфигурацию в экземпляр контейнера. На последнем и финальном шаге мы можем разрешать объекты из экземпляра контейнера.
    После прочтения этого раздела вы приобретете полноценное понимание всей сущности паттерна применения Spring.NET и сможете начать использовать его в сценариях, в которых все компоненты руководствуются должным DI-паттерном, например, Constructor
    Injection. Давайте начнем с простейшего сценария и посмотрим, как можно разрешать объекты с помощью контейнера Spring.NET.
    Разрешение объектов
    Основная услуга, предоставляемая любым DI-контейнером – компоновка диаграмм объектов, и Spring.NET не является исключением. Поскольку это основная возможность контейнера, именно сейчас и стоит приступить к знакомству с соответствующим API, что я и буду делать в этом разделе.
    В предыдущих главах, посвященных Castle W indsor и StructureMap, вы видели, как эти DI- контейнеры по-разному подходят к тому, нужно ли конфигурировать компоненты до того, как можно будет их разрешать. Castle Windsor требует, чтобы мы явно конфигурировали каждый отдельный компонент, а StructureMap может работать с конкретными типами без предварительной конфигурации. Но оба эти DI-контейнера, как и все DI-контейнеры, рассматриваемые в следующих главах, оперируют типами: мы отправляем в контейнер запрос на разрешение соответствующего типа.
    Spring.NET отличается от остальных DI-контейнеров, поскольку его ключевой механизм запросов основывается не на типах, а на именах. Вместо того чтобы запрашивать конкретный тип, мы запрашиваем у Spring.NET именованный объект. По аналогии с Castle
    Windsor все объекты должны быть сконфигурированы до того, как мы сможем их использовать.
    Конфигурирование Spring.NET выполняется в XML, поэтому даже самый простой сценарий включает в себя фрагмент XML, а также некоторый .NET код. К примеру, для того чтобы разрешить конкретный класс
    SauceBéarnaise
    , вы должны сначала задать объект в XML-конфигурации:



    В Spring.NET каждый сконфигурированный объект должен отображаться в элементе object
    . Данный элемент может иметь атрибут id
    , который присваивает имя объекту, а

    458 также атрибут type
    , который определяет .NET тип объекта. Имя используется в тех случаях, когда вы собираетесь разрешить объект.
    Для разрешения экземпляра
    SauceBéarnaise вы должны загрузить XML-конфигурацию в экземпляр контейнера. При помощи
    XmlApplicationContext вы можете загрузить XML из нескольких различных источников, включая вложенные ресурсы и конфигурационный файл приложения. Но в примере ниже используется самостоятельный XML-файл под названием sauce.xm l: var context = new XmlApplicationContext("sauce.xml");
    SauceBéarnaise sauce = (SauceBéarnaise)context.GetObject("Sauce");
    Для того чтобы разрешить экземпляр
    SauceBéarnaise вы вызываете метод
    GetObject c
    ID
    , равным
    Sauce
    , который вы задали для объекта в XML-конфигурации.
    ID
    может быть любой строкой, но Spring.NET рекомендует использовать Pascal нотацию в качестве соглашения по именованию.
    Поскольку метод
    GetObject возвращает слабо типизированный экземпляр
    System.Object
    , чтобы начать его использовать, вам необходимо привести возвращаемое значение к соответствующему типу
    Обратите внимание на то, что Spring.NET явным образом не различает конкретные и абстрактные типы. В то время как другие DI-контейнеры требуют от нас преобразования абстрактных типов в конкретные, Spring.NET основан только на преобразованиях имен в конкретные типы. Как продемонстрирует данная глава, Spring.NET все равно может разрешать запросы преобразования абстракций в конкретные экземпляр ы, но используемый механизм более явный, чем тот, который применяют другие DI- контейнеры.
    Метод
    GetObject определяется интерфейсом
    IObjectFactory
    , который является одним из фундаментальных интерфейсов, задаваемых Spring.NET. Как и подразумевает его имя, интерфейс
    IObjectFactory сконцентрирован на создании объектов и не содержит методы, позволяющие конфигурировать контейнер. Скорее за это отвечают типы более высокого уровня, например,
    XmlApplicationContext
    Метод
    GetObject является одним из нескольких методов, которые можно использовать для разрешения объектов. Тем не менее, поскольку все они слабо типизированы, мы должны всегда явным образом приводить возвращаемо е значение к типу, с которым мы собираемся работать. С помощью метода
    GetObject мы можем запрашиват ь объекты только по имени, а не по типу, поэтому, каким образом мы должны выходить из ситуаций, когда все, что у нас есть – это тип?
    Разрешение запросов типа
    Иногда у нас имеется не имя, а экземпляр
    Type
    , который мы должны разрешить в экземпляр этого типа. Пример этого вы видели в разделе 7.2 "Построение ASP.NET MVC приложений", где мы обсуждали ASP.NET MVC класс
    DefaultControllerFactory
    Соответствующий метод приведен ниже: protected internal virtual IController GetControllerInstance(
    RequestContext requestContext, Type controllerType);

    459
    При наличии типа вместо имени мы могли бы соблазниться заданием и сопровождением явного преобразования типов в имена, но это было бы излишним. Наиболее подходящим вариантом было бы использование соглашения по именованию, которое позволяло бы нам детерминированно наследовать имя от экземпляра
    Type
    . Но интерфейс
    IListableObjectFactory
    , который наследуется напрямую от
    IObjectFactory
    , задает метод под названием
    GetObjectsOfType
    , который можно использовать для получения всех объектов, соответствующих данному типу. Полагая, что запрашиваемый controllerType
    – уникален в конфигурации Spring.NET, вы можете реализовать метод
    GetControllerInstance следующим образом:
    IDictionary controllers = this.context.GetObjectsOfType(controllerType); return controllers.Values.OfType().Single();
    Поле context
    – экземпляр
    IListableObjectFactory
    , который можно запросить для всех объектов, соответствующих controllerType
    . Несмотря на то, что вам возвращается словарь, вам интересны только значения, и при этом вы предполагаете, что каждый запрашиваемый контроллер будет уникальным в пределах упомянутой выше XML- конфигурации.
    Хотя Spring.NET не предоставляет никакого generic API, вы можете легко инкапсулироват ь предыдущий запрос в метод расширения: public static T Resolve(this IListableObjectFactory factory)
    { return factory.GetObjectsOfType(typeof(T))
    .Values.OfType().Single();
    }
    Это позволит вам разрешать тип следующим образом:
    SauceBéarnaise sauce = context.Resolve();
    Метод
    GetObjectsOfType возвращает все сконфигурированные объекты, которые соответствуют запрашиваемому типу. Поскольку
    SauceBéarnaise реализует интерфейс
    IIngredient
    , вы можете также разрешить
    IIngredient из контекста:
    IIngredient ingredient = context.Resolve();
    Т ипичный ASP.NET
    Controller и любой другой код приложения, который мы, скорее всего, напишем, будет иметь сложную иерархию зависимостей. Для того чтобы позволить
    Spring.NET компоновать объекты из слабо связанных сервисов, мы должны обеспечить должную конфигурацию.
    Конфигурирование контейнера
    Как мы уже обсуждали в разделе 3.2 "Конфигурирование DI-контейнеров", существует несколько концептуально разных способа конфигурирования DI-контейнера. На рисунке
    12-3 представлен обзор возможных вариантов и то, какие варианты подходят для
    Spring.NET.

    460
    Рисунок 12-3: Spring.NET из трех возможных вариантов, перечисленных в главе 3, поддерживает, главным образом, XML-конфигурацию. Технология использования кода в качестве конфигурации поддерживает ся в минимальной степени, а автоматическая регистрация вообще недоступна. Поэтому данные варианты отмечены серым цветом.
    Как и другие, имеющие длительную историю DI-контейнеры, Spring.NET сначала использовал XML в качестве основного источника конфигурации. Но в отличие от Castle
    Windsor и StructureMap контейнер Spring.NET продолжает концентрироваться на XML, возможно, из-за его сильных связей с фреймворком Java Spring.
    Технология конфигурирова ния в коде в Spring.NET
    В то время, когда я писал эту главу, Spring.NET не поддерживал технологию конфигурирования в коде. Т ем не менее, буквально за несколько дней до того, как я приступил к финальной части книги, SpringSource выпустил Spring
    CodeConfig
    , который обеспечивает поддержку технологии конфигурирования в коде в Spring.NET.
    К несчастью, это случилось слишком поздно, и у меня не оставалось времени на то, чтобы переписать эту главу.
    В данной главе мы будем рассматривать только XML-конфигурацию.
    Работа с .NET типами в XML
    Spring.NET использует конфигурацию, основанную на XML. Этот XML может браться из разнообразных источников. В большинстве случаев мы будем загружать XML из файла.
    В разделе 12.1.1 "Разрешение объектов" вы уже видели простой пример XML- конфигурации Spring.NET:

    461



    Не секрет, что XML сам по себе является многословным языком, но когда дело доходит до идентификации типов, он становится чересчур многословным. Для того чтобы должным образом идентифицировать .NET тип с помощью строки, мы должны прибегнуть к квалифициро ванным именам сборки. Даже в случаях, когда мы можем опустить
    Culture
    ,
    Version и
    PublicKeyToken
    , тип будет чаще всего идентифицироваться при помощи длинной строки, содержащей множество повторяющейся информации. Это наносит вред как читабельности, так и удобству сопровождения.
    На читабельность оказывается влияние, поскольку соответствующая часть имени типа
    (
    SauceBéarnaise
    ) размещена между пространством имен и именем сборки. Удобство сопровождения подвергается влиянию, поскольку становится сложнее переименовывать пространства имен и сборки. Всякий раз, когда мы что-либо переименовываем, нам приходится редактировать потенциально большой набор определений типов.
    Допустим, эти проблемы применяются ко всем фреймворкам, в которых типы должны задаваться в виде XML, но тогда это еще одна причина того, почему все остальные DI- контейнеры используют для конфигурирования контейнера другие варианты. По этой причине я также чаще всего не рекомендую использовать XML-конфигурацию до тех пор, пока она не будет предписана сценарием применения. Тем не менее, когда дело касается
    Spring.NET, XML – самый распространенный вариант конфигурирования.
    Для облегчения работы с .NET типами в XML SpringSo urce предоставляет такие средства, как XML-схемы и дополнение для Visual Studio с завершением типов и свойств. Сам фреймворк также позволяет нам задавать набор псевдонимов типов, являющихс я сокращенными именами, которые можно использовать для определения типов. Это также выполняется в XML. Псевдоним типа для класса
    SauceBéarnaise может выглядеть следующим образом:

    Имя может быть любым, но мне кажется, чтобы оно было наиболее понятно и его можно было бы легко запоминать, для имени типа следует использовать его псевдоним.
    Указанный псевдоним типа позволяет нам переписать предыдущий пример следующим образом:

    Данная возможность может быть полезна, когда нам нужно несколько раз обратиться к одному и тому же типу в одном и том же XML-файле. В любом случае это делает конфигурацию более читабельной. В оставшейся части данной главы я буду использовать псевдонимы типов. Благодаря такому обозначению элемент object начинает походить на то, чем он является: преобразование имени в конкретный тип.

    462
    В такой простой форме это и есть элемент object
    . При наличии у объектов зависимостей вы должны сообщить Spring.NET , как их необходимо разрешать.
    Явное конфигурирова ние зависимосте й
    Создать класс
    SauceBéarnaise довольно легко, поскольку он имеет конструктор по умолчанию. Ни одному DI-контейнеру не нужно никакой особой помощи для создания таких типов. Все меняется, когда конструктор по умолчанию отсутствует. К примеру, рассмотрим конструктор
    Mayonnaise
    : public Mayonnaise(EggYolk eggYolk, OliveOil oil)
    Несмотря на то, что рецепт майонеза слегка упрощен, и
    EggYolk
    , и
    OliveOil
    – это конкретные классы, имеющие конструкторы по умолчанию. Однако, поскольку класс
    Mayonnaise не имеет конструктора по умолчанию, вы должны сообщить Spring.NET, как его разрешить. Один из вариантов – явным образом одновременно интегрировать типы:






    Т ипы
    EggYolk и
    OliveOil конфигурируются таким же образом, как это делалось ранее, но элемент
    Mayonnaise теперь содержит два элемента constructor-arg
    . Каждый из этих элементов ссылается на именованный объект для того, чтобы определить параметры конструктора
    Mayonnaise
    . Атрибут ref идентифицирует еще один сконфигурированный объект по имени, таким образом,
    EggYolk ссылается на имя
    EggYolk
    , а не явно на тип
    EggYolk
    В предыдущем примере важен порядок элементов constructor-arg
    , поскольку вы не обращаетесь явным образом к именам параметров, что также возможно.
    Несмотря на то, что мы всегда можем сконфигурировать зависимости таким способом, мы не получаем никаких преимуществ, которые предлагает нам механизм автоматической интеграции. В противоположност ь другим DI-контейнерам при работе с Spring.NET мы должны явным образом просить его использовать механизм автоматической интеграции, и все равно этот механизм работает только в конкретных случаях.
    Автоматическая инте грация зависимостей
    Возможности механизма автоматической интеграции в Spring.NET ограничены, но мы должны явным образом переключить его на использование XML-атрибута. Вместо явной интеграции
    Mayonnaise указанным ранеее способом вы могли бы сконфигурировать его следующим образом:




    463
    Необязательный атрибут autowire можно использовать для включения для этого объекта механизма автоматической интеграции. В данном примере мы используем значение autodetect
    , которое сообщает Spring.NET о том, что необходимо точно вычислить, каким образом выполняется поиск соответствующих объектов. Остальные доступные параметры позволяют нам указывать, что поиск соответствующих объектов необходимо выполнять по именам, типам или другими средствами.
    Если мы планируем использовать автоматическу ю интеграцию для всех объектов, то мы можем разрешить ее для целого блока сконфигурированных объектов вместо того, чтобы приписывать атрибут autowire для каждого элемента object
    :





    Атрибут default-autowire задает стратегию автоматической интеграции по умолчанию для всех объектов в рамках элемента objects
    . Это самый простой способ включения автоматической интеграции сразу для всех объектов, но вы должны иметь ввиду, что этот механизм работает не всегда.
    Поддержка автоматической интеграции в Spring.NET основывается на однозначности.
    Spring.NET исследует конструктор класса
    Mayonnaise и определяет, что ему нужны экземпляр ы
    EggYolk и
    OliveOil
    . Для выделения зависимости
    EggYolk он выполняет поиск среди всех остальных сконфигурированных элементов с целью обнаружения элемента, который может удовлетворять данному условию (то же самое он делает и для зависимости
    OliveOil
    ).
    В предыдущем примере есть только один объект, удовлетворяющий зависимости
    EggYolk
    , поэтому неоднозначность отсутствует. Однако если бы данному условию удовлетворя ло более одного объекта, то возникло бы исключение. Это справедливо не только для конкретных элементов
    EggYolk
    , но также и для унаследованных типов.
    П римечание
    В Spring.NET автоматическая интеграция работает только в тех ситуациях, когда зависимости могут разрешаться однозначно. В этом заключается отличие Spring.NET от остальных DI-контейнеров.
    Условие индивидуальности, обеспечивающее поддержку автоматической интеграции, дает нам преимущество, которое заключается в том, что контракт в рамках контейнера является понятным и явным. Автоматическая интеграция возможна только при отсутствии неопределенности, связанной с разрешенными типами, поэтому риск неправильного конфигурирования становится намного меньше. С другой стороны, такое конструирование усложняет работу с составными объектами, реализующими одну и ту же абстракцию.
    Мы рассмотрели некоторые основные опции конфигурации Spring.NET . Несмотря на то, что можно, конечно, написать один большой блок неструктурированного XML кода, лучше всего разделить конфигурацию на модули. Spring.NET поддерживает такую возможность, позволяя XML загружаться более чем из одного источника.

    464
    Загрузка XML
    Иногда нам может потребоваться упаковать конфигурацию в повторно используемые группы, и даже когда повторное использование само по себе не является нашим высшим приоритетом, нам может понадобиться некоторого рода структура в случае необходимости конфигурирования большого и сложного приложения.
    В рамках Spring.NET мы можем упаковать конфигурацию в отдельные XML элементы, которые определены в разных ресурсах. В таблице 12-2 перечисляются поддерживаемые типы ресурсов. Их легко использовать, но я вкратце расскажу о каждом из них, чтобы у вас осталось это в памяти.
    Таблица 12-2: Типы ресурсов XML
    Т ип ресурса
    Синтаксис URI
    Описание
    FileSystemResourc e
    file://
    Моникер
    1   ...   28   29   30   31   32   33   34   35   ...   43


    написать администратору сайта