Presenter Model Viewer - как реализовать сложные свойства во взаимодействии IView - PullRequest
2 голосов
/ 14 августа 2011

Мне трудно понять, как лучше всего реализовать свойства интерфейса IView, которые не являются простыми типами, и мне было интересно, как другие подходят к этому в приложении Model View Presenter.

Статьи, которые я прочитал, действительно хороши, но ни одна из них, похоже, не подходит к более сложным представлениям, где у вас есть свойства List <>, которые имеют тип интерфейса, представляющий класс в вашей доменной модели, то есть IPerson или IName и т. Д. .

Я постараюсь описать сценарий как можно более кратко.

Предположим, у меня есть требование для представления, чтобы в конечном итоге сохранить список имен, каждое из которых состоит из 3 свойств: «Имя», «Фамилия» и «Заголовок».

Как правило, у меня будет модель предметной области с классом «Имя» с тремя свойствами. Эта модель предметной области будет реализовывать интерфейс (в отдельной библиотеке классов «Интерфейсы»), называемый «IName».

Теперь в пространстве имен «Views» в моей библиотеке «Interaces» у меня есть интерфейс под названием «IViewNames». Это интерфейс представления, который будет реализован любым представлением, которое в конечном итоге хочет сохранить список имен.

Как определить этот интерфейс 'IViewNames', меня удивляет. Если я даю ему свойство, подобное:

public List<IName> Names {get;set;}

тогда мой реализующий конкретный вид в конечном итоге будет иметь сложное свойство 'Names', для которого потребуется 'getter', который просматривает поля в представлении, каким-то образом создает экземпляр экземпляра 'IName', устанавливает его свойства, добавляет в список перед возвратом списка. «Сеттер» будет таким же сложным, получая список «INames» и просматривая их, устанавливая поля в представлении.

Мне кажется, что это нарушает одну из основных целей подхода MVP, заключающегося в возможности тщательного тестирования кода приложения без каких-либо конкретных реализаций View. В конце концов, я мог бы легко написать докладчика, который просматривает свойство «View.Names» и отправляет его на сервисный уровень, или устанавливает свойство «View.Names» при получении списка объектов «Name» обратно из сервиса. Слой. Я мог бы легко написать множество тестов, которые гарантируют, что все работает, все, кроме свойства COMPLEX в View.

Итак, мой вопрос: как другие подходят к свойствам IView, которые не являются простыми типами, но на самом деле являются типами вашей доменной модели? (а также типы интерфейсов, которые представляют вашу модель домена, поскольку я явно не хочу, чтобы ссылка из моего уровня представления на уровень моей модели домена).

Я более чем уверен, что существует известная методика для достижения этого элегантным способом, которая соответствует целям Model View Presenter, больше, чем мой примерный подход.

Заранее спасибо за любую помощь людям.

Ответы [ 2 ]

1 голос
/ 11 декабря 2012

Я не очень много работал над шаблоном проектирования MVP, но обязательно попробую его на практике.

Подход 1: Привязка данных

В этом случае вы также можете создатьотдельные свойства в IView и связать эти свойства в Presenter со свойствами модели.Таким образом, ваш взгляд не станет сложным.Опыт быстрый и беспроблемный, поскольку значения из пользовательского интерфейса могут напрямую использоваться в модели.Изменение значения свойства в модели немедленно отразится в пользовательском интерфейсе.Для этого вам, возможно, придется использовать события NotifyPropertyChange.

Подход 2. Сложные типы

Вы можете попробовать создать List или Tuples, чтобы сохранить эти значения и использовать ихведущий.Возможно, вам придется использовать события или действия, чтобы отразить значение от модели до вида и наоборот.

Пожалуйста, дайте мне знать, помогло ли это вам.Спасибо.

0 голосов
/ 25 января 2012

Я взял это объяснение из одной статьи , которую я пишу на моем сайте

Ведущий для просмотра сообщений

Существует два стиля, используемых для заполнения представления данными из Presenter и Model, которые я использовал. Единственное различие между ними заключается в том, насколько тесно вы связаны между собой своим Видом и Моделью. Для примера этого у нас будет следующее в качестве нашей Модели:

public class Person
{
    public int ID { get; private set; }
    public int Age { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    Public Genders Gender { get; set; }
}

Способ 1. Использование модели

Теперь наш код просмотра:

public interface IEmployeesView
{
    void ClearList();
    void PopulateList(IEnumerable<Person> people);
}

И, наконец, ведущий:

public class IEmployeesPresenter
{
    public void Display()
    {
        _view.ClearList();
        _view.PopulateList(_model.AllEmployees);
    }
}

Этот метод заполнения создает связь между моделью и представлением; объект Person, используемый в качестве параметра в PopulateList.

Преимущество этого состоит в том, что конкретная реализация IEmployeesView может решать, что отображать в своем списке людей, выбирая из любого или всех свойств Person.

Это два недостатка этого метода. Во-первых, ничто не мешает представлению вызывать методы на Person, что облегчает вставку ленивого кода. Второе, это то, что если бы модель сменилась с List<Person> на List<Dog> например, нужно будет изменить не только модель и презентатор, но и представление.

Способ 2. Использование общих типов

Заполнение другого метода зависит от использования Tuple<...>, KeyValuePair<,> и пользовательских классов и структур:

Теперь наш код просмотра:

public interface IEmployeesView
{
    void ClearList();
    void PopulateList(IEnumerable<Tuple<int, String> names);
}

И, наконец, ведущий:

public class IEmployeesPresenter
{
    public void Display()
    {
        var names = _model.AllEmployees.Select(x => new Tuple<int, String>(x.ID, x.FirstName + " " + x.LastName));

        _view.ClearList();
        _view.PopulateList(names);
    }
}

Преимущества этого метода заполнения состоят в том, что Модель может свободно изменяться без необходимости обновления Представления, а Представление не имеет никаких решений относительно того, что отображать. Он также не позволяет представлению вызывать какие-либо дополнительные методы для Person, так как на него нет ссылки на него.

Недостатки этого метода в том, что вы теряете строгую типизацию и открываемость. Совершенно очевидно, что такое Person, но что Tuple<int, String> менее очевидно.

...