Ещё один маленький вопросик по освоению DI. Инструментарий — .NET, Unity и WinForms
Пусть у нас есть клиентский контейнер, в котором регистрируются сервисы доступа к данным, например, экземпляр SqlConnection и сервис, инкапсулирующий некую логику работы с данными:
public interface IService
{
Person GetPerson(int id);
}
public class Service : IService
{
[Dependency]
public SqlConnection Connection {get;set;}
public Person GetPerson(int id)
{
var command = Connection.CreateCommand();
command.CommandText = "...";
...
// Конструируем Person
Person person = new Person(reader);
return person;
}
}
public static void Main()
{
var connection = new SqlConnection(connectionString);
container.RegisterInstance<SqlConnection>(connection);
container.RegisterType<IService, Service>();
}
Теперь собственно вопрос: какой именно объект предпочтительнее впрыскивать в экземпляры экранных форм и других самостоятельных элементов управления?
1) Сам контейнер
public class MyForm : Form
{
[InjectionConstuctor]
public MyForm([Dependency] IUnityContainer container) {...}
}
2) Только указатель на интерфейс сервиса
public class MyForm : Form
{
[InjectionConstuctor]
public MyForm([Dependency] IService service) {...}
}
4) Всё сразу и чем больше тем лучше
public class MyForm : Form
{
[InjectionConstuctor]
public MyForm([Dependency] IUnityContainer container) {...}
[Dependency]
public IService Service {get;set;}
[Dependency]
public SqlConnection Connection {get;set;}
}
Здравствуйте, baranovda, Вы писали:
B>Ещё один маленький вопросик по освоению DI. Инструментарий — .NET, Unity и WinForms
B>Пусть у нас есть клиентский контейнер, в котором регистрируются сервисы доступа к данным, например, экземпляр SqlConnection и сервис, инкапсулирующий некую логику работы с данными:
B>
B>код поскипан
B>
B>Спасибо за внимание
ИМХО лучше сразу делать MVP, тогда вопросов с зависимостями не будет.
Запостил и вспомнил, что про презентеры я и забыл.
G>ИМХО лучше сразу делать MVP, тогда вопросов с зависимостями не будет.
Резонно. Но от BindingSource, которые в своём роде тоже являются презентерами, отказываться не хочу.
Спасет ли меня Composite UI Application Block?
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
B>Запостил и вспомнил, что про презентеры я и забыл.
G>>ИМХО лучше сразу делать MVP, тогда вопросов с зависимостями не будет. B>Резонно. Но от BindingSource, которые в своём роде тоже являются презентерами, отказываться не хочу.
Не надо отказываться.
Будет примерно так:
public class XXXForm: Form, IXXXView
{
public XXXForm(IXXXPresenter presentr)
{
presenter.SetView(this); //костыль так как не поддерживаются рекурсивные зависимости
...
}
public void IXXXView.SetDataSourcce(..)
{
//настройка BindingSource
}
}
public class XXXPresenenter: IXXXPresenter
{
public XXXPresenenter(/*здесь все зависимости*/)
{
...
}
...
}
B>Спасет ли меня Composite UI Application Block?
Ну он уже давно на WPF, а если использовать WPF, то лучше MVVM.
Re[2]: DI + UI
От:
Аноним
Дата:
22.06.09 10:47
Оценка:
Здравствуйте, gandjustas, Вы писали:
G>ИМХО лучше сразу делать MVP, тогда вопросов с зависимостями не будет.
А почему не будет?
Ведь всё равно в презентере остаётся та же самая дилема.
Передать в конструктор презентера контейнер или все необходимые сервисы или как контейнер, так и сервисы.
B>Теперь собственно вопрос: какой именно объект предпочтительнее впрыскивать в экземпляры экранных форм и других самостоятельных элементов управления?
B>1) Сам контейнер B>2) Только указатель на интерфейс сервиса
B>4) Всё сразу и чем больше тем лучше
B>Спасибо за внимание
ИМХО не надо вносить зависимость на объект котейнера. Так проще тестировать и лишних зависимостей нет.
Я бы инжектил только сервис который необходим
Здравствуйте, Аноним, Вы писали:
А>Здравствуйте, gandjustas, Вы писали:
G>>ИМХО лучше сразу делать MVP, тогда вопросов с зависимостями не будет. А>А почему не будет? А>Ведь всё равно в презентере остаётся та же самая дилема. А>Передать в конструктор презентера контейнер или все необходимые сервисы или как контейнер, так и сервисы.
Выделение пресентера поможет организовать зависимости, подобная организация в других слоях приведет к тому что подобные вопросы и не будут возникать.
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>Не надо отказываться. G>>Будет примерно так:
B>Примерно так и сделал, в башке утряслось.
B>Ещё маленький вопрос — всякие UI-шные прибамбасы типа курсора ожидания или перехваты исключений — это функция View или таки Presenter-а?
Курсор — однозначно view. Пресентеру лучше вообще не знать о классах System.Windows.Forms.
Перехват исключений лучше делать в пресентере и вызывать View.ReportError(...)
Здравствуйте, gandjustas, Вы писали:
G>Курсор — однозначно view. Пресентеру лучше вообще не знать о классах System.Windows.Forms. G>Перехват исключений лучше делать в пресентере и вызывать View.ReportError(...)
А подскажи, пожалуйста, представление в модели MVP — всегда должно быть строго пассивное и презентер должен данные push-ить в него, или же представление может быть активным и тащить данные из презентера самостоятельно? Поясню на примере:
Пусть у нас есть форма редактирования атрибутов физического лица. При заполнении этой формы активным источником данных является объект типа Person, но в то же время для редактирования свойств объекта активно используются всякие справочники: пол, семейное положение и так далее. Как в модели MVP предполагается заполнять справочники?
1) Представление выставляет методы заполнения этих справочников, которые вызываются презентером:
3) Представление может попросить у презентера ссылку на интерфейс, который возвращает справочные списки
4) Презентер активно проталкивает в представление интерфейс сервиса справочников
Здравствуйте, baranovda, Вы писали:
B>А подскажи, пожалуйста, представление в модели MVP — всегда должно быть строго пассивное и презентер должен данные push-ить в него, или же представление может быть активным и тащить данные из презентера самостоятельно? Поясню на примере:
B>Пусть у нас есть форма редактирования атрибутов физического лица. При заполнении этой формы активным источником данных является объект типа Person, но в то же время для редактирования свойств объекта активно используются всякие справочники: пол, семейное положение и так далее. Как в модели MVP предполагается заполнять справочники?
То, что вы описываете, на самом деле является двумя разновидностями MVP: с пассивным и активным видом (иногда называют push и pull view соответственно).
В первом варианте модель "спускается" виду сверху, и он её рисует. Тут часто применяют дополнительный архитектурный приём, называемый Presentation Model или View Model. Суть его очень проста — дело в том, что в реальном мире в виде редко удаётся обойтись одним объектом доменной модели. Классический пример — вид, отображающий классический заказ — который опять-таки классически состоит из объекта Order и некоторого количества объектов OrderLine. Вот тогда в игру вступает Presentation Model, который комбинирует вышеназванные объекты в один объект, скажем OrderModel, который и скармливается виду. При этом вид имеет возможность (а я бы сказал — необходимость) осуществить глубокую декомпозицию вида на составные части, при этом каждый из "дочерних" объектов отдаётся на рендеринг соответствующему "подвиду". К плюсам данного подхода относится "testing friendliness" как контроллера (ибо достаточно убедиться, что он возвращает правильную модель), так и вида (ибо вид ничего не знает о контроллере, и вообще ему всё равно, откуда эта модель берётся, что позволяет подсунуть ему специально сформированную модель из юнит-теста). Такой вариант применяется, к примеру, в ASP.NET MVC, а также вместе с библиотеками с развитыми средствами биндинга (WPF/SL).
Второй вариант — активный вид, который знает о существовании контроллера и активно это знание использует, вытягивая необходимые данные при необходимости. Честно говоря, тут я слабо представляю механизмы, ибо практического опыта применения данного подхода у меня нет, и с учётом этого подход у меня лично вызывает нехорошие ассоциации с WinForms с логикой в обработчиках ивентов... Так что отсылаю вас к статье на тему MVC на этом сайте. Если же тут есть применяющие active ("pull") view на практике — поделитесь опытом...
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, gandjustas, Вы писали:
G>>Курсор — однозначно view. Пресентеру лучше вообще не знать о классах System.Windows.Forms. G>>Перехват исключений лучше делать в пресентере и вызывать View.ReportError(...)
B>А подскажи, пожалуйста, представление в модели MVP — всегда должно быть строго пассивное и презентер должен данные push-ить в него, или же представление может быть активным и тащить данные из презентера самостоятельно? Поясню на примере:
B>Пусть у нас есть форма редактирования атрибутов физического лица. При заполнении этой формы активным источником данных является объект типа Person, но в то же время для редактирования свойств объекта активно используются всякие справочники: пол, семейное положение и так далее. Как в модели MVP предполагается заполнять справочники?
Вариант с активным view больше похож на паттерн MVVM, он хорошо работает когда есть декларативный байндинг и в нем можно достаточно сложные функциональные зависимости выражать. В отсутствии такого байндинга лучше делать view пассивным, чтобы весь важный код был в пресентере (там его легче тестировать).
Что касается справочников, то нужно сделать множество во view типа SetXXXLookupData(...), смешивать push и pull не стоит.
Здравствуйте, gandjustas, Вы писали:
G>Вариант с активным view больше похож на паттерн MVVM, он хорошо работает когда есть декларативный байндинг и в нем можно достаточно сложные функциональные зависимости выражать. В отсутствии такого байндинга лучше делать view пассивным, чтобы весь важный код был в пресентере (там его легче тестировать).
G>Что касается справочников, то нужно сделать множество во view типа SetXXXLookupData(...), смешивать push и pull не стоит.
Интересно, вот я использую пассивный view в винформсах, но передача активностей через события меня сильно парит. Посему решено делать вместо событий прямые вызовы методов презентера. Ибо это проще тестируется и требует меньше кода. Я смешал push и pull? Какие минусы в таком подходе?
Здравствуйте, Ziaw, Вы писали:
Z>Здравствуйте, gandjustas, Вы писали:
G>>Вариант с активным view больше похож на паттерн MVVM, он хорошо работает когда есть декларативный байндинг и в нем можно достаточно сложные функциональные зависимости выражать. В отсутствии такого байндинга лучше делать view пассивным, чтобы весь важный код был в пресентере (там его легче тестировать).
G>>Что касается справочников, то нужно сделать множество во view типа SetXXXLookupData(...), смешивать push и pull не стоит.
Z>Интересно, вот я использую пассивный view в винформсах, но передача активностей через события меня сильно парит. Посему решено делать вместо событий прямые вызовы методов презентера. Ибо это проще тестируется и требует меньше кода. Я смешал push и pull? Какие минусы в таком подходе?
можно код? а то на словах не очень понятно.
Во многих статьях про MVP авторы осторожно утверждают, что комбинирование View и Presenter-а какбе допустимо, но не рекомендуемо, потому что можно легко запутаться и утерять преимущества декомпозиции
Здравствуйте, baranovda, Вы писали:
B>Здравствуйте, Ziaw, Вы писали:
B>Во многих статьях про MVP авторы осторожно утверждают, что комбинирование View и Presenter-а какбе допустимо, но не рекомендуемо, потому что можно легко запутаться и утерять преимущества декомпозиции