MVVMLight: это правильный способ использования Messenger? - PullRequest
1 голос
/ 27 июля 2011

У меня есть классическое бизнес-приложение, которое управляет клиентами и адресами.

Существуют элементы вкладок (Id, GenericInfo и некоторые другие), каждый из которых имеет собственную ViewModel.

Существует MainViewModel, который обрабатывает команды сохранения и загрузки клиента и его адреса.

Мы получаем данные из службы WCF. Данные, полученные / отправленные из каждой функции WCF, агрегируются в другой контейнер.


В моей MainViewModel я создаю SaveContainer, а затем отправляю его с мессенджером.

    public void Save()
    {
        var container = new SaveContainer();

        MessengerInstance.Send(container);

        //the container is now populated and ready to be sent via WCF

        Console.WriteLine(container.User.Name);
        Console.WriteLine(container.Address.StreetName);
        Console.WriteLine(container.Address2.StreetName);
    }

В моем UserViewModel регистрируется этот контейнер, а затем viewmodel заполняет его имеющимися данными (пользователь).

    public UserViewModel()
        : base(Messenger.Default)
    {
        User = new User();

        MessengerInstance.Register<SaveContainer>(this, (x) => x.User = User);
    }

И в моей AddressViewModel я делаю то же самое.

    public AddressViewModel()
        : base(Messenger.Default)
    {
        Address = new Address();
        Address2 = new Address() { StreetName = "Washington Street" };

        MessengerInstance.Register<SaveContainer>(this, x =>
        {
            x.Address = Address;
            x.Address2 = Address2;
        });
    }

Я бы сделал то же самое, когда мне нужно загрузить данные.


После отправки сообщения я предполагаю, что каждый зарегистрированный ViewModel получил сообщение и обработал его. Я ошибаюсь? Считаете ли вы таким образом правильный способ использования Messenger? Что бы вы улучшили?

Ответы [ 2 ]

2 голосов
/ 30 июля 2011

Нет правильного способа использования мессенджера. Однако вам следует учитывать, что сообщение обрабатывается всеми получателями, которые зарегистрировались для сообщения, а не только предполагаемым подмножеством. Кроме того, при использовании обмена сообщениями вы не можете контролировать, когда обработка сообщения завершена, теперь вы получаете уведомление, когда все получатели закончили обработку сообщения. Кроме того, в зависимости от реализации мессенджера, сообщения могут обрабатываться параллельно.

Так что проблема с вашим подходом (и расширением @ cadrell0, использующим обратный вызов) заключается в том, что вы не знаете, когда все получатели обработали сообщение. Используя обратный вызов, вы получите обратный вызов для каждого получателя, обрабатывающего сообщение (т.е. n получателей и n обратных вызовов).

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

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

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

Так, где же это вас покинет ... в вашем сценарии я бы предпочел проектировать модели представления как «связанные» (т. Е. Модель основного вида знает о модели представления пользователя и модели представления адреса - или модель основного вида знает о модели представления пользователя, которая в свою очередь знает о моделях представления адреса, если это более уместно). Обычно я также хотел бы разработать модель, содержащую единицу работы, с которой мне приходится иметь дело (в вашем случае SaveContainer). Затем все модели представлений строятся из этой модели и записывают в нее свои данные. В обычных случаях эта единица работы - это то, что вы получаете от службы хранения данных, а что, в свою очередь, сохраняется в хранилище данных за одну транзакцию.

Но, опять же, нет правильного пути к MVVM!

0 голосов
/ 27 июля 2011

Если мне нужно что-то сделать после того, как получатель ответит на сообщение, я включу в свой ответный вызовКогда получатель сделан, он выполняет обратный вызов.Добавление параметров к обратному вызову позволяет получателю отправлять данные отправителю.Это также позволяет получателю выполнить асинхронную операцию.

...