Tuesday, December 10, 2013

Использование Spring.Net

Продолжаем знакомство с серией статей об IoC контейнерах для управления зависимостями. На этот раз “жертвой” критики станет IoC контейнер Spring.Net. Предыдущие статьи были посвящены таким IoC контейнерам, как Unity, Autofac, CastleWindsor и StructureMap. Spring.Net - это портированный с языка Java IoC контейнер. По отношению к анализируемому IoC контейнеру было упомянуто слово “жертва”, что вписывается в данный контекст его описания, поэтому сразу предупреждаю об этом поклонников Spring.Net перед ознакомлением с данным материалом. На момент написания статьи была доступна версия 1.3.2, и за два года с момента использования этого контейнера в последний раз не произошло существенных изменений. Приведу интересную схему, описывающую работу контейнера, взятую с официального сайта, посвященного Spring.Net.

Как видите, судя по рисунку, все довольно просто: достаточно сконфигурировать в xml файле - и можно просто использовать. Ниже приведена диаграмма классов для демонстрации работы данного IoC контейнера. Для примера использовалась связка WPF + MVVM.
Основная модель представления представлена классом MainViewModel. С помощью этой модели и будет продемонстрирована вся мощность Spring.Net. Рассмотрим, как будет реализован самый простой сценарий constructor injection (CI) для класса MainViewModel, чтобы посмотреть на Spring.Net в действии. Чтобы инициализировать IoC контейнер перед стартом программы, необходимо перейти в классыApp.xaml.cs и переопределить метод OnStartup.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <configSections>
    <sectionGroup name="spring">
      <section name="objects" type="Spring.Context.Support.DefaultSectionHandler, Spring.Core" />
    </sectionGroup>
  </configSections>

  <spring>
    <objects xmlns="http://www.springframework.net">
      <object id="LibraryBook" type="SpringDemo.Model.LibraryBook, SpringDemo"/>
      <object id="LibraryBookService" type="SpringDemo.Model.LibraryBookService, SpringDemo"/>
      <object id="MainViewModel" type="SpringDemo.ViewModel.MainViewModel, SpringDemo">
       <constructor-arg ref="LibraryBookService" />
      </object>
    </objects>
  </spring>

</configuration>
Пример файла конфигурации для настройки IoC контейнера Spring.Net с реализацией:
using (var container = new XmlApplicationContext("config://spring/objects"))
{
    var model = container.GetObject("MainViewModel");
    var view = new MainWindow { DataContext = model };
    view.Show();
}
Как видим из примера, использовать Spring.Net несложно. Многие разработчики могут сказать, что же в этом подходе не так. Пожалуй, отвечу на этот вопрос более обширно. Данный подход наверняка очень понравится любителям NHibernate, так как они привыкли использовать xml для конфигурирования связей с БД. Теперь пройдусь по негативным (по субъективной оценке) моментам касательно Spring.Net, основным из которых является полное отсутствие конфигурирования и настройки данного IoC контейнера, кроме xml.
Получить нужную реализацию можно с помощью метода GetObject. Этот метод возвращает тип Object. Мне действительно не понятно, почему нельзя было сделать хотя бы extension методы, чтобы не приводить явно к нужной реализации. Хотя здесь я переборщил, так как уже вышла пререлиз-версия 2.0, в которую наконец добавили GetObject<T>, который позволяет возвращать сразу новый тип. Многие могут возразить, что не проблема привести с Object к нужному типу. Соглашусь, это не проблема, но зачем это делать, если есть множество IoC контейнеров, которые позволяют делать то же самое без лишних усилий с вашей стороны.
При установке с помощью NuGet Packages данный IoC контейнер грузит поддержку для всех типов .Net Framework. Это выглядит так:
Спрашивается, зачем нужно тащить, указав в сборке проекта 4 фреймворк, 35 Мб библиотеки, которые мне, по сути, не нужны.
Почему-то проект с использованием Spring.Net долго собирается. Единственный IoC контейнер, который почему-то инициализируется так же долго это CastleWindsor. Но он в несколько раз превосходит по возможностям данный контейнер, так что это можно отнести в раздел маленьких неудобств.
Разработчики данного IoC контейнера заявляют о поддержке аспектного программирования (interception), что является достоинством данного контейнера. Но какие популярные контейнеры не имеют такой особенности? На момент написания статьи такую возможность имеют StructureMap, CastleWindsor, Unity и Autofac.

Итоги
В данной статье был приведен краткий обзор IoC контейнера Spring.Net. Материал по отношению к данному контейнеру имеет характер критики. С моей точки зрения, этот контейнер уступает всем популярным контейнерам. Надеюсь, после ознакомления с материалом Вы обратите внимание на другие IoC контейнеры, часть из которых описана в предыдущих статьях, и выберете наиболее целесообразно подходящий.
Источники:

No comments:

Post a Comment