Измените текущую реализацию базового MVVM, чтобы она соответствовала шаблону SOLID.

Я писал все свои приложения MVVM с базовым шаблоном проектирования, обычно упоминаемым в примерах MVVM, доступных в Интернете. Шаблон, которому я следую, описан ниже:

Модель

Этот раздел включает классы DTO с их свойствами и интерфейсами IDataService и тому подобное:

 public class Employee
 {
   public string EmployeeName { get; set; }
   public string EmployeeDesignation { get; set; }
   public string EmployeeID { get; set; }
 }

public interface IDataService
{
  public Task<Employee> GetEmployeeLst();
}

Прокси

Этот уровень содержит вызовы Dataservice, которые реализуют IDataservice, например:

public class DataService : IDataService
{
   public async Task<Employee> GetEmployeeLst()
   {
     // Logic to get employee data from HTTPClient call
   }
}

Модель представления

Этот слой содержит ViewModel и ссылку на уровень Model и Proxy, из которого получены все данные:

public class BaseViewModel
{
    public BaseViewModel(INavigationService nav, IDataService data, IAESEnDecrypt encrypt, IGeoLocationService geoLocation, IMessageBus msgBus, ISmartDispatcher smtDispatcher)
    {
    }

    // This also include common methods and static properties that are shared among most of the ViewModels
}

Все ViewModel наследует BaseViewModel. Каждая модель представления также содержит команду делегата, которая выполняется, когда пользовательский интерфейс запускает событие. Который затем извлекает данные с сервера, вызывая DataService на уровне прокси, выполняет бизнес-логику и заполняет свойства в ViewModel, которые привязаны к представлению. Для каждого представления существует виртуальная машина, привязанная к контексту данных представления. ViewModel также отвечает за запуск анимации. Я использовал триггер для запуска раскадровки, которая привязана к моим перечислениям в виртуальной машине для изменения состояния этих триггеров, как в примере: http://www.markermetro.com/2011/05/technical/mvvm-friendly-visual-state-management-with-windows-phone-7/

Просмотреть

На этом уровне у меня есть все мои представления, пользовательские элементы управления и бизнес-логика с реализацией определенных зависимостей, таких как служба геолокации, шифрование AES, служба навигации между представлениями и т. д.

Каждое представление имеет файлы .xaml и .xaml.cs. В файле .xaml.cs я связал контекст данных представления с виртуальной машиной следующим образом:

this.DataContext = App.IOConatiner.GetInstance<DashboardViewModel>();

и с этого момента происходит всякое связывание.

Моя проблема в том, что недавно я узнал, что этот шаблон не соответствует шаблону проектирования SOLID, о котором я узнал в этом ответе на мой вопрос: Простой инжектор внедряет несколько зависимостей в базовый класс

Я очень стараюсь изменить свой дизайн в соответствии с предложением, данным в ответе на мой предыдущий вопрос. Но я не могу получить некоторые вещи, такие как:

  1. В настоящее время View Datacontext привязан к ViewModel, поэтому все элементы управления контролируются свойством в виртуальной машине. Как бы я изменил это на ваш вышеупомянутый шаблон с помощью Processor/Service или DialogHandler?

  2. Я использую Delegatecommands, которые привязаны к свойству команды элемента пользовательского интерфейса. При выполнении этой команды происходит определенное действие, например, анимация, отображается пользовательский контроль. Как это сделать в шаблоне команды?

  3. Как я могу начать изменять свою текущую реализацию, чтобы приспособить все эти изменения наилучшим образом?


person Balraj Singh    schedule 08.02.2015    source источник
comment
@Ric.Net, не могли бы вы мне помочь?   -  person Balraj Singh    schedule 08.02.2015
comment
@Ric.Net, я подробно задал вопрос. Если возможно, обратите внимание на это.   -  person Balraj Singh    schedule 09.02.2015
comment
Как сказал @Ric.Net в другом ответе, потеряйте базовый класс. Избавьтесь от BaseViewModel. Это первый шаг. Это мгновенно покажет вам, какие службы требуются для каждой виртуальной машины. Затем вы можете следовать примеру, приведенному в этом очень подробном ответе.   -  person qujck    schedule 09.02.2015
comment
Хорошо, я пытаюсь только это   -  person Balraj Singh    schedule 09.02.2015


Ответы (2)


Прежде всего ответ на ваш вопрос 3

Как я могу начать изменять свою текущую реализацию, чтобы приспособить все эти изменения наилучшим образом?

Это самый первый шаг, который вам нужно сделать. Это не случай умного рефакторинга вашего текущего кода. Вам нужно будет сделать шаг назад и разработать приложение. Однажды я прочитал хороший блог о (ре)дизайне.

Прежде чем приступить к написанию какого-либо кода, определите, сколько различных основных типов представлений вы хотите показать пользователю? Например.:

  1. Просто покажите (любой тип) данные
  2. Изменить данные
  3. Предупредить пользователя
  4. Попросите пользователя ввести
  5. ...

Когда вы определили свои различные требования, вы можете преобразовать их в конкретные интерфейсы, созданные специально для работы, которую они выполняют. Например, представление, которое позволяет пользователю редактировать данные, обычно имеет интерфейс, который будет выглядеть примерно так:

public interface IEditViewModel<TEntity>
{
    public EditResult<TEntity> EditEntity(TEntity entityToEdit)();
}

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

Имея эту структуру, вы можете приступить к кодированию своих реализаций.

В настоящее время View Datacontext привязан к ViewModel, поэтому все элементы управления контролируются свойством в виртуальной машине. Как бы я изменил это на ваш вышеупомянутый шаблон с помощью Processor/Service или DialogHandler?

Это не изменится в этом дизайне. Вы по-прежнему будете привязывать свое представление к своей модели представления и устанавливать контекст данных для модели представления. При большом количестве просмотров пригодится инфраструктура MVVM, такая как Caliburn Micro. Это сделает за вас многое из того, что касается MVVM, на основе Соглашение важнее конфигурации. Чтобы начать с этой модели, кривая обучения будет еще выше, поэтому мой совет начинать вручную. Таким образом вы узнаете, что происходит под обложкой такого инструмента MVVM.

Я использую Delegatecommands, которые привязаны к свойству команды элемента пользовательского интерфейса. При выполнении этой команды происходит определенное действие, например, анимация, отображается пользовательский контроль. Как это сделать в шаблоне команды?

Я не уверен, что шаблон команды, который вы здесь упоминаете, является командой pattern Я советовал вам в предыдущем ответе. Если это так, я думаю, вам нужно перечитать этот блог, потому что это совершенно не связано с командами, которые, как я думаю, вы имеете в виду в этом вопросе.

За анимацию и подобные вещи отвечает представление, а не модель представления. Таким образом, представление должно обрабатывать все эти вещи. В XAML есть много способов справиться с этим. Больше, чем я могу объяснить здесь. Некоторые идеи: Триггеры, Свойства зависимостей

Другой вариант: код позади! Если логика связана исключительно с представлением IMO, то размещение этого кода в коде позади вашего представления не является смертным грехом. Просто не поддавайтесь искушению делать что-то серое!

Для команд, которые просто выполняют вызов метода в вашей модели представления, ICommand по-прежнему возможен, и инструменты MVVM, такие как Caliburn, будут делать это автоматически...

И еще: освободите базовый класс....

person Ric .Net    schedule 11.02.2015
comment
Спасибо, Рик. Нет. Теперь я понимаю, о чем вы говорите. Просто хочу уточнить, что Delegate Command, о которой я здесь говорю, является реализацией интерфейса ICommand, предназначенного для привязки свойства команды кнопки к ее реализации. В чем разница между этой ICommand и командой, которая использует шаблон команды: cutedge.it/blogs/steven/pivot/entry.php?id=91 имеет в виду? - person Balraj Singh; 12.02.2015
comment
@BalrajSingh: ICommand WPF является реализацией шаблона Gang of Four Command. Этот шаблон предназначен для пользовательских интерфейсов, где может быть важно отменить/повторить действие. Шаблон, описанный здесь, не имеет официального названия, но я обычно называю его шаблоном "команда/обработчик". '. Он особенно подходит для бизнес-логики. Отличие шаблона команды состоит в том, что команда/обработчик отделяет данные (команду или сообщение) от поведения (обработчика), в то время как шаблон команды GOF помещает данные и поведение в один класс (команду). - person Steven; 13.02.2015
comment
@Steven На самом деле я до сих пор использую команду GOF, поэтому шаблон команды / обработчика для меня новый. Пытаюсь понять, какую часть кода я могу переместить в шаблон команды/обработчика. - person Balraj Singh; 13.02.2015
comment
@BalrajSingh Это просто: ВСЯ ваша бизнес-логика. - person Steven; 13.02.2015

Почему вы внедряете все эти службы в базовый класс модели представления, если базовый класс модели представления не использует эти службы сам?

Просто внедрите нужные вам сервисы в производные модели представления, которым эти сервисы нужны.

person Philip Stuyck    schedule 08.02.2015
comment
На самом деле у меня есть несколько общих команд, которые используются в разных представлениях, таких как Signout. В моем приложении выход из системы может быть выполнен из нескольких представлений, поэтому я сохранил это в своем базовом представлении, которое также использует вызов службы. - person Balraj Singh; 08.02.2015
comment
И для этого нужны все 6 этих сервисов? Опубликуйте этот код, пожалуйста, иначе слишком сложно понять вашу точку зрения. - person Philip Stuyck; 08.02.2015