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
}
});