Лучшая практика для синхронизации моделей и ViewModels

Я работаю над большим приложением Silverlight, которое использует дуплексный протокол Net.TCP для взаимодействия с серверной частью WCF. Я занимаюсь переводом этого приложения с подхода MVC на MVVM. Однако я не могу найти правильный способ реализовать свои модели представления. Мы используем сгенерированные WCF прокси для нашей модели, которая довольно сложна, включает в себя десятки классов, множество коллекций и множество отношений «многие ко многим». Например, пользователь может принадлежать ко многим комнатам, у комнаты может быть много пользователей, у пользователя может быть много SharedFiles, и каждый SharedFile может использоваться совместно с любой комнатой, частью которой пользователь в настоящее время является. Что-то в этом роде.

Кроме того, поскольку мы используем WCF в дуплексном режиме, изменения в модели могут быть инициированы либо конечным пользователем, либо службой WCF на сервере. Другими словами, модель, которую мы используем, на несколько порядков сложнее типичной «Модели», которую вы видите в любой из различных книг / статей / сообщений в блогах по MVVM. И вот тут-то и возникает проблема, потому что синхронизация нашего слоя ViewModel с нижележащим слоем модели становится проблемой.

Вот типичная проблема. Новый «Пользователь» присоединяется к «Комнате», поэтому службы WCF запускают уведомление «SessionAdded» для всех других пользователей в комнате. Уведомление SessionAdded содержит объект Session, который имеет связанную комнату и связанный объект User. Этот объект Room, который десериализуется из службы WCF, в основном такой же, как объект Room на локальном клиенте, и, вероятно, имеет большинство тех же данных, но определенно не имеет всех одинаковых данных, и, по крайней мере, некоторые данные (например, его коллекция пустых досок) определенно неверны. Поэтому нам нужно каким-то образом взять эти входящие данные и объединить их с нашей существующей моделью. И затем нам нужно создать ViewModels поверх каждого из новых объектов и / или обновить существующие ViewModels новыми объектами и / или их данными.

Прямо сейчас мы решаем эту проблему, заставляя различные модели представления реагировать на соответствующие события уведомления WCF и делать все возможное, чтобы исправить свои базовые модели и связанные модели представлений.Мы придумали несколько уловок, например SynchronizedObservableCollection (смутно похожий на ту здесь ), которая наблюдает (скажем) на Room.Sessions ObservableCollection и автоматически создает соответствующие модели SessionViewModels и помещает их в коллекцию RoomViewModel.SessionViewModels. Мы также используем ViewModelFactory, который кэширует модели представления и гарантирует, что, скажем, SessionViewModel, который обертывает данный сеанс, остается неизменным, даже если базовый объект сеанса изменяется. (Если это важно, мы используем подход, основанный на представлении модели, поскольку большая часть того, что нам нужно, - это создание новых элементов пользовательского интерфейса в ответ на изменения в модели представления, вызванные нашими уведомлениями WCF.)

И все такое. из этого работает. По сути. Большую часть времени. Тебе известно. Но нужно поддерживать много кода, и в нем легко ошибиться. Модульные тесты удобны, если вы помните, что должно произойти, но к тому времени, когда вы закончите обработку своего 20-го каскадного события CollectionChanged, трудно отслеживать, как все это сочетается друг с другом и что вы тестировали в первую очередь. . Другими словами, все это чертовски хрупкое.

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

(1) Рассматривайте модель на стороне клиента как своего рода базу данных, которая должна быть полностью согласованной, и реализовать уровень доступа к данным на стороне клиента, задача которого заключается в том, чтобы модель оставалась последовательной.Все обновления модели, будь то от пользователя или от сервера, должны проходить через этот уровень. Это будет немного похоже на Entity Framework, поскольку myRoom.Users.Add (myUser) автоматически установит myUser.Room = myRoom , и наоборот, и так далее. (Это особенно та часть, которая кажется, что кто-то где-то уже должен был разработать,хотя я еще не нашел его.)

(2) Опирайтесь на что-то вроде Ферма или Obtics , чтобы синхронизировать все части. Пока не совсем уверен, как это сработает, но в теории звучит так, как будто это должно быть возможно.

И ... что еще? Мне любопытно, какие шаблоны или фреймворки использовались для решения этой проблемы.

6
задан Ken Smith 11 February 2011 в 15:31
поделиться