У меня есть клиент WCF, который передает объекты самопроверки в приложение WPF, созданное с помощью MVVM. Само приложение имеет динамический интерфейс. Пользователи могут выбирать, какие объекты они хотят видеть в своей рабочей области, в зависимости от того, в какой роли они находятся или какую задачу они выполняют.
Мои объекты с самопроверкой имеют довольно много свойств навигации, и многие из них не нужны.
[WCF] <---> [ClientSide Repository] <---> [ViewModel] <---> [View]
Мои модели являются объектами с самопроверкой. Репозиторий на стороне клиента подключает метод LazyLoad (при необходимости) перед возвратом модели в модель представления, которая ее запросила. Все вызовы службы WCF асинхронны, что означает, что методы LazyLoad также асинхронны.
Фактическая реализация LazyLoad доставляет мне некоторые проблемы. Вот варианты, которые я придумал.
РЕДАКТИРОВАТЬ - Я удалил образцы кода, чтобы упростить чтение и понимание. См. Предыдущую версию вопроса, если вы хотите ее увидеть
Вариант A
Асинхронная отложенная загрузка свойств модели с сервера WCF в Getter
Хорошо: Загрузка данных по запросу чрезвычайно проста. Привязка в XAML загружает данные, поэтому, если элемент управления находится на экране, данные загружаются асинхронно и уведомляют пользовательский интерфейс, когда они появляются. Если нет, ничего не загружается. Например,
загрузит данные, однако, если раздел «Документы» интерфейса отсутствует, ничего не загружается.
Плохо: Нельзя использовать это свойство в любом другом коде до его запуска, потому что он вернет пустой список. Например, следующий вызов всегда будет возвращать false, если документы не были загружены.
public bool HasDocuments
{
get { return ConsumerDocuments.Count > 0; }
}
ВАРИАНТ B
Выполнение вызова для загрузки данных вручную, когда это необходимо
Хорошо: Просто реализовать - просто добавьте ] LoadConsumerDocumentsSync ()
и LoadConsumerDocumentsAsync ()
методы
Плохо: Необходимо не забыть загрузить данные перед попыткой доступа к ним, в том числе когда они используются в привязках. Это может показаться простым, но это может быстро выйти из-под контроля. Например, у каждого ConsumerDocument есть UserCreated и UserLastModified. Существует DataTemplate, который определяет UserModel со всплывающей подсказкой, отображающей дополнительные данные пользователя, такие как расширение, электронная почта, команды, роли и т. Д. Итак, в моей ViewModel, которая отображает документы, мне нужно было бы вызвать LoadDocuments
, а затем выполнить цикл их и вызовите LoadConsumerModified
и LoadConsumerCreated
. Это тоже могло бы продолжаться ... после этого мне пришлось бы LoadUserGroups
и LoadUserSupervisor
. Также существует риск возникновения циклических циклов, когда что-то вроде Пользователь
имеет свойство Группы []
, а Группа
имеет Пользователи []
свойство
ВАРИАНТ C
На данный момент мой любимый вариант ... создать два способа доступа к свойству. Одна синхронизация и одна асинхронная передача. Привязки будут выполняться со свойством Async, и любой код будет использовать свойство Sync.
Хорошо: Данные загружаются асинхронно по мере необходимости - именно то, что я хочу. Не так уж и много дополнительного кода, поскольку все, что мне нужно было сделать, это изменить шаблон T4 для создания этих дополнительных свойств / методов.
Плохо: Наличие двух способов доступа к одним и тем же данным кажется неэффективным и запутанным. Вам нужно помнить, когда следует использовать Consumer. ConsumerDocumentsAsync
вместо Consumer.ConsumerDocumentsSync
. Также существует вероятность того, что вызов службы WCF запускается несколько раз, и для этого требуется дополнительное свойство IsLoaded для каждого навигационного свойства, например IsConsumerDocumentsLoaded.
ВАРИАНТ D
Пропустите асинхронную загрузку и просто загрузите все синхронно в сеттеры.
Хорошо: Очень просто, никаких дополнительных действий не требуется
Плохо: Блокирует пользовательский интерфейс при загрузке данных. Не хочу этого.
ВАРИАНТ E
Попросите кого-нибудь из SO сказать мне, что есть другой способ сделать это, и указать мне на образцы кода :)
Другие примечания
Некоторые из NavigationProperties будут загружается на WCF-сервер перед возвратом объекта клиенту, однако другие слишком дороги для этого.
За исключением ручного вызова событий загрузки в варианте C, все это можно сделать с помощью шаблона T4, поэтому мне нужно сделать очень мало кода. Все, что мне нужно сделать, это подключить событие LazyLoad в клиентском репозитории и указать его на правильные вызовы службы.