powered by simpleCommunicator - 2.0.51     © 2025 Programmizd 02
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / MVVM - Модели представления с наследованием - оцените подход
10 сообщений из 10, страница 1 из 1
MVVM - Модели представления с наследованием - оцените подход
    #38582662
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оцените подход к проектированию моделей представления с наследованием, основанных на моделях с наследованием. Хочется узнать ваше мнение о плюсах и минусах такого подхода. Ну и как что улучшить.


Пусть есть модель ModelA:

Код: c#
1.
2.
3.
4.
public class ModelA
{
    public int NumberA { get; set; }
}



Пусть есть ModelB, унаследованная от ModelA:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
public class ModelB : ModelA
{
    public int NumberB { get; set; }

    public ModelB(ModelA modelA)
    {
        NumberA = modelA.NumberA;
    }
}



Если у нас, как в классическом подходе
(
http://msdn.microsoft.com/ru-ru/magazine/dd419663.aspx
http://joshsmithonwpf.wordpress.com/2008/11/14/using-a-viewmodel-to-provide-meaningful-validation-error-messages/
),
модели представления выглядят как классы, содержащие у себя неоткрытое поле, хранящее модель, то неплохо бы вынести эту логику в базовый класс для таких моделей представления (сокращение VM означает ViewModel):

// Base_VM - базовый класс для вообще всех моделей представления, а не
// только для тех, которые содержат поле-модель

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
public abstract class ModeledBase_VM<TModel> : Base_VM
{
    protected readonly TModel _modelObject;

    protected TModel ModelObject
    {
        get { return _modelObject; }
    }

    public ModeledBase_VM(TModel modelObject)
    {
        _modelObject = modelObject;
    }
}



А вот так будут выглядеть модели представления для моделей А и B - всё через наследование:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
public class ViewModelA : ModeledBase_VM<ModelA>
{
    public int NumberA
    {
        get { return ModelObject.NumberA; }
        set { ModelObject.NumberA = value; }
    }

    public ViewModelA(ModelA modelA)
        : base(modelA)
    { }
}

public class ViewModelB : ViewModelA
{
    public int NumberB
    {
        get { return ((ModelB)ModelObject).NumberB; }
        set { ((ModelB)ModelObject).NumberB = value; }
    }

    public ViewModelB(ModelB modelB)
        : base((ModelA)modelB) // сделал явное приведение (хотя оно здесь и не обязательно),
                               // чтобы было легче понять тем, кто не знаком с иерархией классов моделей
    { }
}



Обратите внимание, что в коде моделей представления в явном виде нет поля, содержащего модель. Единственный минус - в базовом классе (ModeledBase_VM<TModel>) моделей представления ссылка на модель хранится с типом сАмого базового класса модели, так что, чтобы получить свойства более унаследованных моделей в более унаследованных моделях представления, нужно явно приводить их к этим более унаследованным моделям, как показано во ViewModelB. Но по идее, модель представления знает, что за модель она представляет, так что это, я думаю, допустимо.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38582663
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Ещё вопрос. Есть ли какое правило по проектирования моделей представления (МП) в зависимости от того, как спроектированы модели? Скажем, если в моделях наследование, то и в МП наследование. Если в моделях включение (т. е. не наследование, а когда поля модели имеют тип других моделей), то и в МП тоже. Или МП проектируются так, как удобнее, вне зависимости от моделей?

Тут есть ещё соображение, что часто в представления являются иерархическими. Т. е. надо представить модель представления, некоторые свойства которой требуют отдельных представлений, т. к. сами тоже возвращают модели представления (подход "включение"). Т. е. тут включение очень бы подошло. Но что, если модель спроектирована через наследование? В таких случаях я думаю использовать конструкцию вида (на примере ViewModelB выше)

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
private ViewModelA _viewModelA;
public ViewModelA ViewModelA
{
    if (_viewModelA == null)
        _viewModelA = new ViewModelA(ModelObject);

    return _viewModelA;
}
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38583611
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Изменил базовый класс моделей представления так, чтобы было немного безопаснее с приведением типов. Соответственно, в унаследованных моделях представления тоже немного поменялось обращение к модели:

Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
public abstract class ModeledBase_VM : Base_VM
{
    protected readonly object _modelObject;

    public TModel GetModelObject<TModel>()
    {
        Type modelObjectActualType = _modelObject.GetType();
        Type typeOfTypeParameter = typeof(TModel);

        if (modelObjectActualType.IsAssignableFrom(typeOfTypeParameter))
            return (TModel)_modelObject;
        else
            throw new InvalidCastException();
    }

    public ModeledBase_VM(object modelObject)
    {
        _modelObject = modelObject;
    }
}




Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public class ViewModelA : ModeledBase_VM
{
    public int NumberA
    {
        get { return GetModelObject<ModelA>().NumberA; }
        set { GetModelObject<ModelA>().NumberA = value; }
    }

    public ViewModelA(ModelA modelA)
        : base(modelA)
    { }
}



Код: c#
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
public class ViewModelB : ViewModelA
{
    public int NumberB
    {
        get { return GetModelObject<ModelB>().NumberB; }
        set { GetModelObject<ModelB>().NumberB = value; }
    }

    public ViewModelB(ModelB modelB)
        : base(modelB)
    { }
}
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38583616
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Теперь код свойств в унаследованных моделях представления стал более единообразным, а из базового класса ушёл параметр типа модели в классе, который был практически бесполезен. Параметр типа модели перешёл в дженерик метод, возвращающий модель, где ему самое место.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38583619
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пока единственный недостаток вижу - многословность. Длинное название методы, плюс ещё параметр типа, плюс скобочки (в C# нет дженерик-свойств - пришлось дженерик метод делать).
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38583794
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Выкинул слово Object из GetModelObject - стал чувствовать себя лучше.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38583893
megazoid007
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
user7320,
Вообще насколько мне известно идеологический ViewModel подстраивается под View, т.е. ViewModel выгибают так что бы она представляла данные так как нужно, мне кажется данный способ сгодится для самых простых View, а там где нужна композиция данных это провальный способ. Вы сами ответь себе на вопрос вам так проще ? Для меня лично наследование было бы усложнением.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38584114
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
megazoid007user7320,
Вообще насколько мне известно идеологический ViewModel подстраивается под View, т.е. ViewModel выгибают так что бы она представляла данные так как нужно, мне кажется данный способ сгодится для самых простых View, а там где нужна композиция данных это провальный способ. Вы сами ответь себе на вопрос вам так проще ? Для меня лично наследование было бы усложнением.
Я каких только мнений насчёт ВМ не встречал. И то, что она должна подстраиваться под В, и то, что она не должна знать об устройстве В (вот В должно - оно же привязки раскидывает), а только устанавливаться в его контекст данных. И про модель то же самое - "должна" и "не должна".

Классически, насколько я знаю, более верхняя часть (чем ближе к UI, тем "выше") знает об устройстве более нижней. МВ знает о полях М, В знает о полях МВ, но не наоборот.

Другими словами: как правило, на одну М может быть несколько МВ, на одну МВ - несколько В. Но не наоборот. Так что это В подстраивается под МВ. Но могут быть исключения. По крайней мере, я допускаю, что они могут быть.



Конкретно про мой подход - он, в основном, для МВ, работающих с М с наследованием. Поэтому я и создал отдельный класс ModeledBase_ViewModel. Для моделей со включением, если создавать МВ со включением - возникает проблема дублирующихся моделей. У вас одна модель хранится в текущей МВ, а другая - в свойстве этой текущей МВ, которое представляет из себя тоже МВ. А теперь попробуйте обновить свойство включённой МВ - придётся обновлять и свойство включённой, и свойство текущей. Т. е. при обновлении свойства самой нижней включённой МВ придётся в сеттере самой верхней вызвать всю цепочку обновлений - с нижнего включения до верхнего.

А для представлений включение - самое то, т. к. через шаблоны данных можно строить иерархические представления: В для МВ, потом через шаблон данных и юзерконтрол делаем В для свойства МВ, которое тоже, в свою очередь, МВ - и т. д. Я так делал.



Однако, могут быть разные ситуации, и иногда бывает нужно нарушить правила. Кроме того, во фреймворках, поддреживающих MVC (ASP.NET MVC, например), некоторые тоже пытаются вводить ВМ. Одни считают за ВМ собственно М в ASP.NET MVC, и добавляют ещё один слой М (уже настоящих, труМ - собственно, модели предметной области). При этом, если начать использовать какой-нибудь Нокаут (knockoutjs), то куда в этой терминологии отнести его МВ - непонятно. Надо ли делить МВ на МВ сервера (МВС) и МВ клиента (МВК)? Это всё ещё не устоялось и навряд ли когда устоится. Поэтому в подобных ситуациях правила нарушаются повсеместно, т. к. по сути нет никаких правил. И рвать глотки на форумах друг другу тоже имеет мало смысла, т. к. кто в какой области "наблатыкался", тот и пытается везде свой опыт насовать. А те, кто имеет опыт во многих областях и умеют выносить адаптированные конвергентные решения, обычно не доживают или им некогда - они у Гугла с МСом на поминутной оплате сидят.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38594042
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
В этом посте надо поменять местами типы в методе IsAssignableFrom - плохое знание английского меня подвело. Надо так:

Код: c#
1.
if (typeOfTypeParameter.IsAssignableFrom(modelObjectActualType))



В базовой модели представления в поле _modelObject всегда хранится модель с приведением к самому базовому типу. А те, кто запрашивают метод GetModelObject<TModel>(), уже сами указывают, к какому типу эту модель надо привести - самому базовому или выше ниже по иерархии наследования.
...
Рейтинг: 0 / 0
MVVM - Модели представления с наследованием - оцените подход
    #38594043
user7320
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторсамому базовому или выше ниже по иерархии наследования.
...
Рейтинг: 0 / 0
10 сообщений из 10, страница 1 из 1
Форумы / WPF, Silverlight [игнор отключен] [закрыт для гостей] / MVVM - Модели представления с наследованием - оцените подход
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]