Здравствуйте, IB, Вы писали:
IB>А зачем Presenter в сессию класть? Во-первых это просто по логике Stateless класс, а во-вторых, даже если в каком-то конкретном случае это окажется не так, то есть паттерн memento, с помощю которого можно вынести состояние в отделную сущность и хранить его спокойно где надо.
Ага. В ASP.NET 2.0 есть готовое решение — ViewState, сохранение состояния. А, к примеру, в Eclipse, точнее в jface, есть также готовое решение, которое называется одноименно с шаблоном проектирования — интерфейс IMemento и поддержка его со стороны визуальных форм.
Здравствуйте, IB, Вы писали:
IB> Но цель статьи, как я уже писал, была не предоставить готовое приложение или описать особенности использования MVP в ASP.Net, а показать саму идею паттерна и его возможности по смене представлений. Если писать приложение по всем правилам, то сам паттерн замажется, а хотелось его-то в первую очередь и показать.
И действительно, MVC/MVP в любом случае всего лишь каркас... точнее даже часть каркаса приложения. Смысла приводить полное описание готового решения на все случаи жизни нет. Во-первых, сложно будет разобраться, во-вторых, как и отметил IB, сущность каркаса MVC будет донельзя размыта, разнесена по другим не менее важным каркасным сущностям приложения. К примеру, DAL, попробуйте привести описание частной реализации скрещивания MVC и DAL — все... пиши-пропало.
Здравствуйте, eugals, Вы писали:
E>Довольно много орфографических ошибок для статьи напечатанной на бумаге и продаваемой за деньги.
Это наверно претензии не к автору, а к редакторам? Вроде бы раздел есть соответствующий... по журналу.
Здравствуйте, rsn81, Вы писали:
R>Ага. В ASP.NET 2.0 есть готовое решение — ViewState, сохранение состояния.
... на клиенте. Вот вы тут все вумными словами кидаетесь, прошу, покажите мне реализацию (code) хоть Memento хоть SessionProvider хоть ViewState применительно к ASP.NET когда SessionState=Server
Здравствуйте, dotnetcoder, Вы писали:
D>... на клиенте. Вот вы тут все вумными словами кидаетесь, прошу, покажите мне реализацию (code) хоть Memento хоть SessionProvider хоть ViewState применительно к ASP.NET когда SessionState=Server
Прошу прощения, но не понял просьбы. Как бы какая-то "закавыка" в просьбе присутствует, вот только не пойму, в чем она?
Если серьезно, то пример кода в документации несложно найти.
Здравствуйте, dotnetcoder, Вы писали:
D> Вот вы тут все вумными словами кидаетесь, прошу, покажите мне реализацию (code) хоть Memento хоть SessionProvider хоть ViewState применительно к ASP.NET когда SessionState=Server
Memento: http://dofactory.com/Patterns/PatternMemento.aspx
На словах, суть паттерна проста как рельс — если надо как-то сохранить внутреннее состояние объекта, не трогая сам объект, то надо создать новую сущность, которая будет хранить это состояние и объект должен уметь свое состояние сохранить в эту сущность и восстановиться из нее.
ServiceProvider — по сути универсальный интерфейс для хранилища состояний, будь-то сессия, ViewState, куки, watever... Иными словами хранилище memento-объектов, реализация которого зависит от ситуации, нужд разработчика и цены огурцов на стамбульском базаре в прошлый четверг — не суть.
Далее все просто. Presenter берет в одну руку какую-то реализацию ISessionProvider, в другую memento объект с состоянием, и либо сохраняет одно в другом, либо восстанавливает объект из хранилища, смотря что системе нужно в данный момент.
Здравствуйте, rsn81, Вы писали:
R>Здравствуйте, dotnetcoder, Вы писали:
D>>... на клиенте. Вот вы тут все вумными словами кидаетесь, прошу, покажите мне реализацию (code) хоть Memento хоть SessionProvider хоть ViewState применительно к ASP.NET когда SessionState=Server R>Прошу прощения, но не понял просьбы. Как бы какая-то "закавыка" в просьбе присутствует, вот только не пойму, в чем она? R>Если серьезно, то пример кода в документации несложно найти.
Хорошо, давайте рассмотрим конкретный пример :
дано ASP.NET 2.0 с SessionState = Server, надо реализовать MVP для WebApp:
Есть View — SomeUserControl (SomeUserControl.ascx)
Есть Presenter — C# Class
Есть Model — в данном случае XmlNode который возвращает WebService
Для того что бы View дёргла Presenter ссылку на её надо, как предложил автор статьи, хранить в Presenter.
public class Presenter
{
private Model _model = new Model();
private IView _view;
}
Время жизни Presenter это время жизни Session (иначе Presenter придётся каждый раз создавать, что не есть хорошо) соответственно Session хорошее место для его хранения (а в ViewState его засовывать это вообще бред ) но в вышеуказанной конфигурации реализация MVP усложняется, тем что приходится лепить костыли для хранения Presenter в памяти.
Я реализовал MVP для вышеуказанной конфигурации и оно работает, так что это трудности не составляет, но вдруг окажется что есть более лучшие варианты
Сильно упрощённо, моя схема была примерно такая :
public interface IView
{
IPresenter Controller
ViewCallBackHandler(ControllerCommandBase command)
}
public interface ICommand
{
}
public interface IPresenter
{
void OnCommand(IView view, ICommand command); //command = class ViewCommandBase : ICommand
}
public interface IService
{
XmlNode GetData(ControllerCommandBase command) // command = class ControllerCommandBase : ICommand
}
public class SomePresenter : IPresenter
{
public virtual void OnCommand(IView view, ICommand command)
{
if ( command is SomeViewCommand) CommandHandler(view, command as SomeViewCommand)
}
public virtual ControllerCommandBase MapCommand(ViewCommandBase viewCommand)
{
return commandTable[viewCommand];
}
public void CommandHandler(IView view, SomeViewCommand command)
{
ConcreteControllerCommand cmd = MapCommand(command);
SomeDate data = Service.GetData(cmd);
view.ViewCallBackHandler(new AnotherControllerCommand("Refresh",new ControllerEventArgs(data)))
}
public IService Service
{
get{ return ServiceFactory.GetService(); }
}
}
ControllerManager лежит в Application и создается по Application_Start (дада, лочим конечно ), и держит в себе control_id И ссылку на IPresenter который создаётся в IPresenter Controller по Singleton и добавляется при первом вызове get в ControllerManager. ControllerManager реализует IDisposable и уничтожается по Application_End .
Здравствуйте, dotnetcoder, Вы писали:
D>дано ASP.NET 2.0 с SessionState = Server, надо реализовать MVP для WebApp:
D>Есть View — SomeUserControl (SomeUserControl.ascx) D>Есть Presenter — C# Class D>Есть Model — в данном случае XmlNode который возвращает WebService
Выглядеть это может примерно так:
Сначала описываем необходимые интерфейсы...
public interface IMemento
{
// здесь описать всякие методы и свойства необходимые для идентификации
// и управления хранящемся объектом
//
}
// интерфейс к сессии если вздумается хранить не в сессии, а в куках или во вьюстейте
// или вообще не хранить, если это десктоп приложение, достаточно подпихнуть нужную
// реализацию этого интерфейса
//public interface ISessionProvider
{
void Save(IMemento Memento);
T Restore<T>() where T : IMemento;
}
Дальше пошли реализации.
// хранитель данных модели
//public class ModelMemento : IMemento
{
private XmlNode _node;
public XmlNode Node
{
get { return _node; }
set { _node = value;}
}
}
// сама модель должна уметь сохраняться и восстанавливать свое состояние из Memento
//public class Model
{
.......
public void Restore(ModelMemento Memento)
{
Node = ModelMemento.Node;
}
public IMemento Save()
{
ModelMemento memento = new ModelMemento();
memento.Node = Node;
return memento;
}
}
Теперь надо реализовать хранение мементо в сессии:
// в данном случае, для простоты, объекты хранятся по полному имени
//public class SessionProvider : ISessionProvider
{
private HttpSessionState _session =
HttpContext.Current.Session;
public void Save(IMemento Memento)
{
_session[typeof(T).FullName] = Memento;
}
public T Restore<T>() where T : IMemento
{
return (T) _session[typeof (T).FullName];
}
}
Ну и осталось реализовать Presenter:
public class Presenter
{
private Model _model = new Model();
private IView _view;
private ISessionProvider _session;
// в конструкторе поддгружаем данные из сессии, если они там есть
// и восстанавливаем состояние модели
//public Presenter(IView view, ISessionProvider session)
{
_session = session;
ModelMemento modelMemento = _session.Restore<ModelMemento>();
if (modelMemento != null)
_model.Restore(modelMemento);
_view = view;
....
}
// При изменении модели, сохраняем ее состояние в сессии.
//private void OnModelChange(object sender, EventArgs e)
{
.....
_session.Save(_model.Save());
}
}
D>Время жизни Presenter это время жизни Session
Нет. Presenter — это stateless объект, у него нет внутреннего состояния, которое надо хранить, он реализует лишь поведенческую логику. Зачем его запихивать в сессию?
D> (иначе Presenter придётся каждый раз создавать, что не есть хорошо)
Почему не хорошо? По умолчанию контроллером/презентером служит CodeBehind страничка, которая наследник Page, неужели ты и ее в сессию кладешь?
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, dotnetcoder, Вы писали:
D>>дано ASP.NET 2.0 с SessionState = Server, надо реализовать MVP для WebApp:
D>>Есть View — SomeUserControl (SomeUserControl.ascx) D>>Есть Presenter — C# Class D>>Есть Model — в данном случае XmlNode который возвращает WebService
IB> // сама модель должна уметь сохраняться и восстанавливать свое состояние из Memento IB>Теперь надо реализовать хранение мементо в сессии:
Теперь тоже самое, но сохранять Presenter.
D>>Время жизни Presenter это время жизни Session IB>Нет. Presenter — это stateless объект, у него нет внутреннего состояния, которое надо хранить, он реализует лишь поведенческую логику. Зачем его запихивать в сессию?
*)Так как запланирована внутренняя коммуникация между контроллерами, но споткнулся на правильной реализации Presenter.
D>> (иначе Presenter придётся каждый раз создавать, что не есть хорошо) IB>Почему не хорошо?
Смотри *)
IB>По умолчанию контроллером/презентером служит CodeBehind страничка, которая наследник Page, неужели ты и ее в сессию кладешь?
Здравствуйте, dotnetcoder, Вы писали:
D>Теперь тоже самое, но сохранять Presenter.
И какие проблемы? Для Presenter-а создается точно такой же memento объект как и для модели, если вдруг потребовалось состояние presenter-а хранить. Разницы никакой.
D>*)Так как запланирована внутренняя коммуникация между контроллерами, но споткнулся на правильной реализации Presenter.
И? Каким образом наличие комуникации между презентерами влияет на наличие или отсутствие у presenter-а состояния?
D>Естественно нет
Ну а почему тогда presenter так хочется в сессию запихнуть?
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, dotnetcoder, Вы писали:
D>>Теперь тоже самое, но сохранять Presenter. IB>И какие проблемы? Для Presenter-а создается точно такой же memento объект как и для модели, если вдруг потребовалось состояние presenter-а хранить. Разницы никакой.
Вот-вот, прошу пожалуста код, и не забыть сделать SessionState=Server.
D>>*)Так как запланирована внутренняя коммуникация между контроллерами, но споткнулся на правильной реализации Presenter. IB>И? Каким образом наличие комуникации между презентерами влияет на наличие или отсутствие у presenter-а состояния?
D>>Естественно нет IB>Ну а почему тогда presenter так хочется в сессию запихнуть?
коротко — потому-что надо мне так надо, так как считаю реализацию ASP.NET out-of-the-box неудобной для EA.
Здравствуйте, dotnetcoder, Вы писали:
D>Вот-вот, прошу пожалуста код, и не забыть сделать SessionState=Server.
В восьмой раз говорю, код ничем не будет отличаться от того что я привел. Выносишь состояние Presenter-а в отдельный объект (memento) и хранишь как я показал. Хоть в sessionState=server, хоть в куках, хоть у себя в кармане.
Я не пойму, проблема что ли вынести состояние presenter-а в отдельный объект?
D>коротко — потому-что надо мне так надо,
Не, тебе так не надо.. В крайнем случае тебе надо хранить не presenter в сессии, а его состояние. А для того чтобы сохранить его состояние надо вынести это состояние в отдельный объект — это сложно?
Если уж не хочется создавать сам presenter, храни его в кеше, в конце-концов, а зависимое от пользователя состояние так же в memento.
D> так как считаю реализацию ASP.NET out-of-the-box неудобной для EA.
Хм.. Замнем для ястности. Если в "правильной" реализации предполагается хранение presenter-а в сессии, то лучше ASP.Net..
Здравствуйте, siv, Вы писали:
siv>Не по существу статьи... siv>В тексте встретилась очепятка "задачь" siv>Может стоит исправить?
Вообще, в тексте много опечаток и несуразиц, например, как можно унаследоваться от System.Windows.Forms?
Статья в целом неплохая, но вот эти оплошности оставляют неприятный осадок. Для ресурса такого уровня это выглядит очень странно
Неужели никто не делает корректуру перед публикацией?
У меня возник следующий вопрос по статье.
В ней, как я понял из примера, описывается работа с пассивной моделью.
Но вот как быть если данные из View-a через Presenter-a попадают в модель
а далее модель по данным производит какие то действия(внутренние расчеты/обращения к источнику данных и т.п) и получает
новую информацию для отображения, далее ей требуется обновить один или несколько View-ов.
Как тогда получается взаимодействие модели View-а и Presenter-a ?
Можель обновляет вид только через Presenter или сама взаимодействует с видом (но тогда разрушается шаблон MVP)?!!!
Или же это уже не чистый MVP а нечто типа "Supervising Controller "?
Вобщем "все смешалось в королевстве Датском... тьфу в моей голове"
Здравствуйте, Jericho113, Вы писали:
J>В ней, как я понял из примера, описывается работа с пассивной моделью.
Именно.
J>Как тогда получается взаимодействие модели View-а и Presenter-a ?
View и Presenter взаимодействуют точно так же... Presenter знает что он что-то поменял в модели, опрашивает модель на предмет изменений и обновляет соответствующие View. Если в системе существуют несколько независимых Presenter-ов, то внесший изменения презентер может взаимодействовать с остальными через события, либо ввести еще одину триаду уровнем выше, которая через свой презентер контролирует все нижележащие...
J>Модель обновляет вид только через Presenter
При таком раскладе только через Presenter.
J> или сама взаимодействует с видом (но тогда разрушается шаблон MVP)?!!!
Строго говоря не разрушается, но мне такой расклад не симпатичен.. В крайнем случае я предпочитаю, чтобы модель уведомляла презентеры, но не вью.
J>Или же это уже не чистый MVP а нечто типа "Supervising Controller "?
Supervising Controller — всего лишь один из вариантов MVP...
Здравствуйте, IB, Вы писали:
IB>Здравствуйте, Jericho113, Вы писали:
J>>В ней, как я понял из примера, описывается работа с пассивной моделью. IB>Именно.
ок значит я что то еще понимаю в этой жизни
J>>Как тогда получается взаимодействие модели View-а и Presenter-a ? IB>View и Presenter взаимодействуют точно так же... Presenter знает что он что-то поменял в модели, опрашивает модель на предмет изменений и обновляет соответствующие View. Если в системе существуют несколько независимых Presenter-ов, то внесший изменения презентер может взаимодействовать с остальными через события, либо ввести еще одину триаду уровнем выше, которая через свой презентер контролирует все нижележащие...
Значит тут есть жесткая связка модели и Presenter-a. Я так понимаю что Presenter должен подписаться на некоторые события модели которые уведомляют о
изменении модели и соотвецтвующим образом изменить View и остальные Presenter-ы которые с ним связаны?!
Если так тогда более менее понятно.
Тогда вот такой момент поправте если что не так к примеру во View есть кнопка с сохранием текущего документа или же чего бы то ни было.
Далее логика обработки события от этой кнопки переходит в Presenter и он определяет (используя состояние модели или еще как либо ) что в данный момент можно сохраниться или показывает соотвецтвующий диалог, а далее если что пошло не так то отлавливает все исключения и в соотвецтвующим образом модифицирует модель и/или View. Т.е. вся логика работы программы разделяется в моедли и Presenter-e а View не имеет собственной логики.. Ход мыслей правилен или может я всетаки что то упустил?
Здравствуйте, Jericho113, Вы писали:
J>Значит тут есть жесткая связка модели и Presenter-a.
Только со стороны Presenter-а, который естественно знает о модели с которой работает, модель же о presenter-е ничего не знает.
J> Я так понимаю что Presenter должен подписаться на некоторые события модели которые уведомляют о J>изменении модели и соотвецтвующим образом изменить View и остальные Presenter-ы которые с ним связаны?!
Не обязательно.. Presenter же сам вносит изменения, следовательно знает, что модель изменилась и на основании этого может и опросить модель и разослать уведомления — нет необходимости навешивать на модель события.
J> Т.е. вся логика работы программы разделяется в моедли и Presenter-e а View не имеет собственной логики..
Совершенно верно. Основная идея — сделать View как можно проще и повозможности вообще лишить его логики.
Вот не могу всетаки полностью мозгами принять подход MVP, тяжело после MVC перестроиться
Никак не соображу блин как в подход предлагаемый MVP может вписаться биндинг, т.е. автоматическая
привязка данных к контролу ...
Мои мысли по этому поводу
1) привязку (указанние что на что биндить) данных к View-у может осуществитиь Presenter
2) при изменении значений во View-е,Presenter-у прийдется вклиниваться в биндинг и каким то образом перехватывать
измененные значения и запихивать их в модель... или же пропускать мимо себя данные от View-а прямо к модели. Но так появляется
связь View-а и Модели что является разрушением шаблона MVP, т.к. имхо для разделения вида и модели при помощи
внесения между ними посредника в виде Presenter-а, он предназначен.
3) Отказаться от биндинга и руками прописывать связи всех полей данных в контролы и так же в событиях их отслеживать.
(но по моему это никуджа не годится — назад в каменый век).
Вобщем мозги еще не до конца не переварили этот шаблон. Хотя без биндинга он нормально проходит.