После видео про управление зависимостями в коде многие интересуются, как же сделать тоже самое в классическом ASP.NET. Проблема в том, что нужно найти точку старта для активного внесения зависимостей. В ASP.NET MVC она создана за нас – это фабрика контроллеров IControllerFactory.
По решению этой проблемы есть довольно много статей, я дам на них ссылки и добавлю свои комментарии.
Дмитрий Воробьёв прислал мне ссылку на серию отличных видео про использование IoC-контейнеров в ASP.NET . Наиболее интересная статья из этой серии – Unity IoC Dependency Injection and ASP.NET Model-View-Presenter.
Очень важно понимать, что ASP.NET WebForms – это только один из способов работы пользователя с данными вашей системы. От aspx-страницы требуется только отобразить данные или вернуть ввод пользователя. Хочу предостеречь вас от ошибки. Не пытайтесь писать бизнес-логику прямо в code-behind. Её нельзя протестировать и такой подход ведёт к многочисленному дублированию кода и ошибкам в проектировании.
Для ASP.NET и Windows-приложений лучше всего использовать шаблон Model-View-Presenter. Отличное описание этого шаблона вы найдете в книге Роберта Мартина Agile Principles, Patterns, and Practices in C# в главе The Payroll User Interface: MODEL VIEW PRESENTER. В этой главе подробно рассмотрено, как применять шаблон MVP и преимущества, которые мы получаем:
- разделение отображения данных View и их подготовки и обработки Presenter
- возможность модульного тестирования
Кроме этого, перед нами открывается новая возможность – использование IoC-контейнера. Точкой старта для активного внесения зависимостей будет создание Presenter'а.
Я реализовал одно из возможных решений и добавил его в исходный код проекта с ASP.NET MVC. Вся реализация находится в двух проектах: Web.Classic и Web.Classic.UI. Можете развивать его дальше и, если получится что-то интересное, присылайте мне. Рассмотрим его достоинства и выложим исходный код.
Более элегантное решение
Одной из возможных альтернатив моему решению может быть использование фабрики aspx-страниц. Подход подробно описан в статье Inversion of Control and Dependency Injection with WebForms. Это решение чем-то напоминает фабрику контроллеров в ASP.NET MVC.
Хотелось бы в примере хоть какого-нибудь инпута. И не только с текстбокса по щелчку на кнопку. Какой-нибудь FormView бы рассмотреть
ОтветитьУдалить@Dimonina
ОтветитьУдалитьОк. Кроме FormView еще с чем-нибудь есть проблемы?
да я в общем на входные данные хотел бы посмотреть, просто когда такой банальный вывод - это все равно просто и понятно. Да, разложили "по полочкам", можно оттестировать, все красиво и клево.
ОтветитьУдалитьНо взять тот же ListView с пейджером. Для вывода пейджинга (не знаю как в новом 4.0 асп.нет, может придумали что-то) нужно обязательно использовать какой-нибудь ХХХдатасурс. Взять тот же обджектдатасурс. Для вывода списка с пейджером (асп.датапейджер) должна работать связка
ListView -> ObjectDataSource -> HelperClass -> BizLogic.
Где хелперкласс - некая прокся на бизнес-логику, грубо говоря
GetListOfItems(int startRowIndex, int maximumRows)
{
return this._itemLogic.AllItems().Skip(startRowIndex).Take(maximumRows);
}
Получается что вызов логики идет не из странички, которая в пейдж-лоаде функцию презентера дергает, а из отдельного хелпер-класса к обджектдатасурсу. Как туда инжектировать зависимости? Очевидно, создав базовый хелпер и в его конструкторе зарезолвить зависимости, как это сделано, допустим, для юзерконтролов в каком-то примере из статьи. И как в таком случае сюда подрутить модель MVP? Делать зависимым хелпер-класс от презентера а не от логики напрямую? Хотелось бы в общем по составным контролам какой-нибудь опыт увидеть, потому что в простом примере все понятно. Если нужно, могу тестовый проект сделать с комментариями.
@Dimonina
ОтветитьУдалитьНа самом деле все проще, чем вы думаете.
Закомитил в исходники пример работы с ListView.
Чтобы вам было легче дальше продвигаться в этой теме, прочитайте главу из книги Роберта Мартина http://my.safaribooksonline.com/0131857258/ch38
в ней очень подробно рассмотрено применение шаблона MVP.
Спасибо, Саш. Про мвп обяз почитаю.
ОтветитьУдалитьСкачал ЛистВью демо. Собственно это опять простой пример c датабайндингом. Я говорил о связке ListView и DataPager. В примере из SVN-а номер страницы задается по квери-стринг параметру, но самого пейджера на странице не нашел (запустить проект не могу, на данной машине только экспресс версия веб-девелопера 2010, чета не хочет). То есть в данном случае пейджер придется реализовать самостоятельно?
@Dimonina
ОтветитьУдалитьЕсли честно, я не понимаю в чем проблема =)
Можно и нужно использовать элементы отображения, которые тебе удобны. Например, используй DataPager, только данные для него подготовь в Presenter, а не в code-behind.
Так в том то и дело что есть такой затык, что нельзя использовать датапейджер и листвью без использования компонента ХХХдатасурс на странице, который, в свою очередь (если речь про обжект датасурс) требует ссылки на класс с логикой или проксей на логику, иначе пейджинг не будет работать. Я сейчас посмотрю как с этим дело в 4 фреймворке, если сделали возможность задавать без датасурсов - вопрос снят, иначе проблема для меня остается открытой. Давай так, я покопаюсь в 4 аспнете, напишу че нарыл :-)
ОтветитьУдалить@Dimonina
ОтветитьУдалитьОк, но будет лучше, если ты пришлешь мне реализацию ListView и DataPager с использованием MVP. Пиши на мыло, как будут результаты. Если не получится, то я добавлю в исходники свою версию =)
В таком случае, при использовании MVP нам нет необходимости в сборке BusinessLogic.Services, т.к. вся логика будет в presenter?
ОтветитьУдалить@s-stude
ОтветитьУдалитьВ презентере будет логика управления UI (в данном случае WebForms), а в слое бизнес-логики работа с сущностями, выполнение бизнес-операций, например, активация аккаунта или добавления продукта в корзину. Презентер может только попросить бизнес-логику о выполнении этих операций.
Cуществует какая-то очередность при байнде зависимостей? Т.к. у меня сейчас вылетает StackOverflowException в Ninject.Core
ОтветитьУдалить(Пытаюсь разрешить зависимости, использую еще MVP для WinForms)
И еще один момент - не совсем ясен процесс ресолвинга presenter'a во view. У меня, почему-то, возвращается или новый инстанс view или presenter'a
ОтветитьУдалить@s-stude
ОтветитьУдалить> Cуществует какая-то очередность при байнде зависимостей?
Нет
> У меня, почему-то, возвращается или новый инстанс view или presenter'a
Надо смотреть код. Скидывайте мне на почту
ASP.NET - это и так MVP, совершенно не вижу смысла усложнять себе жизнь вводя еще один presenter.
ОтветитьУдалитьВ чистом ASP.NET для разрыва зависимостей DI подходит не очень, но можно воспользоваться фабриками, которые являются все тем же IoC.
@Nikolay Sergeev
ОтветитьУдалить> ASP.NET - это и так MVP
С большой натяжкой. В случае кодбехайнда есть проблемы с модульным тестированием, инжектированием зависимостей, повторным использованием кода.
> воспользоваться фабриками, которые являются все тем же IoC
Опять же с большой натяжкой. Для разрешения зависимостей в коде IoC гораздо удобнее фабрик. Фабрики просто инкапсулируют логику создания объектов - это да. Но у них нет единого места в настройки биндингов интерфейсов и реализаций, настройки жизненного цикла, уже не говоря о гибком конфигурировании, которое сейчас имеют большинство IoC-контейнеров.