MVVM-Light: куда поместить вызов WCF во ViewModel

Я создаю приложение WP7, которое получает все свои данные через службы WCF. Я хочу реализовать в нем MVVM-Light, но в уроках, которые я сделал, я вижу, что в ViewModelLocator он хочет создать статический экземпляр всех моих ViewModel при запуске приложения. Моя проблема в том, что в моих конструкторах для моей виртуальной машины я делаю вызовы WCF, и результаты, конечно же, возвращаются в обратном вызове. Именно в обратном вызове я присваиваю результаты моей наблюдаемой коллекции, которую видят мои представления. Это прекрасно работает, когда не используется MVVM-Light, но если я его реализую, у меня не будет этих вызовов WCF при запуске, поскольку они передают параметры, которые неизвестны / недоступны, пока пользователь не использует приложение (выбор элементов и т. Д.). Я попытался переместить свои вызовы. к WCF получателю моей наблюдаемой коллекции, но он продолжает вызывать WCF в бесконечном цикле. Во всех примерах MVVM-света, которые я видел, я не видел, чтобы кто-то вызывал службы WCF. Какие-нибудь предложения относительно того, куда поместить мои звонки WCF в модели?

3 ответа

Как и всегда в MVVM нет правильного пути... как это касается feedom ...:-)

Вы можете поместить код в модель представления, если хотите. Однако тогда вам также потребуется сгенерировать данные времени проектирования в модели представления - если вы хотите их использовать.

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

редактировать

Внедрение в моем посте не означает, что вы используете контейнер / инфраструктуру для инъекций, это лишь означает, что вы используете интерфейс для абстрагирования своего поведения службы, а затем передаете разработчик или этот интерфейс в конструктор вашей модели представления. Теперь вы можете передавать различные реализации интерфейса при создании модели представления, например, в локаторе представления.

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

Инверсия контейнеров управления - например, ninject, unity и т. Д. - просто помогает автоматически разрешать зависимости, однако они не требуются для использования в версии шаблона управления in.

Я не думаю, что это хорошо, чтобы поместить вызов WCF во ViewModel, вы должны инкапсулировать вызов WCF в другом классе. Ваша ViewModel должна содержать только логику GUI. Я думаю, что вы получаете от вызова WCF модель, вы можете использовать модель для создания ViewModel.

Вот мой пример моего файла CommonServiceHelper.cs

   public void GetUserSettings(UserInfoIn input, Action<UserInfoOut, Exception> callback)
    {
        var proxy = new CommonServiceClient();

        try
        {
            proxy.GetUserSettingsCompleted += (sender, eventargs) =>
            {
                var userCallback = eventargs.UserState as Action<UserInfoOut, Exception>;
                if (userCallback == null)
                    return;

                if (eventargs.Error != null)
                {
                    userCallback(null, eventargs.Error);
                    return;
                }
                userCallback(eventargs.Result, null);
            };
            proxy.GetUserSettingsAsync(input, callback);
        }
        catch (Exception ex)
        {
            proxy.Abort();
            //ErrorHelper.WriteErrorLog(ex.ToString());
        }
        finally
        {
            if (proxy.State != CommunicationState.Closed)
            {
                proxy.CloseAsync();
            }
        }
    }

Затем в ViewModel я называю это так:

               var serviceCommon = new CommonServiceHelper();
                            serviceCommon.GetUserSettings(userSettingsInput, (result, error) =>
                            {
                                if (result != null && error != null)
                                {
                                    //everything is ok
                                }
                                else
                                {
                                    //handle errors
                                }
                            });
Другие вопросы по тегам