проблема с RX и загрузкой коллекции веб-сервисов wp7

Я новичок с платформой С# и wp7, и у меня есть некоторые проблемы с хорошей идеей получить запрос от веб-службы.

Я сделал веб-сервис на PHP (nusoap - WSDL), и все работает нормально при «нормальном» использовании. Теперь у меня есть ObservableCollection, сохраненный в IsolatedStorage, с загрузкой, когда страница открыта (список наблюдаемых стеков обменивается). Затем я хочу обновить данные для каждого элемента из веб-службы.

Я не знаю, хорошая ли это идея.

Код:

private GPWWebservicePortTypeClient client = new GPWWebservicePortTypeClient();
private ObservableCollection<WebServiceClass.ItemGetValues> StoredStock = 
                      new ObservableCollection<WebServiceClass.ItemGetValues>();     
public const string _fileName = "listaObserwowanych.xml";
public Page()
{
   InitializeComponent();

   DataContext = App.ViewModel;

   this.Loaded += new RoutedEventHandler(Page_Loaded);

   client.GetLastValueCompleted +=
            new EventHandler<GetLastValueCompletedEventArgs>(client_GetLastValueCompleted);

   foreach (var itemGetValuese in App.ViewModel.Items)
   {
      client.GetLastValueAsync(itemGetValuese.name);
   }

   var o = 
       Observable.FromEvent<GetLastValueCompletedEventArgs(client,"GetLastValueCompleted")
                                                           .Subscribe(setList);
}

void client_GetLastValueCompleted(object sender, GetLastValueCompletedEventArgs e)
{
    if (e.Error != null)
    {
        MessageBox.Show(Convert.ToString(e.Error));
    }
    else
    {
        ObservableCollection<WebServiceClass.ItemGetValues> ListValues = 
          (ObservableCollection<WebServiceClass.ItemGetValues>)                                                                      
           JsonConvert.DeserializeObject(e.Result, 
           typeof(ObservableCollection<WebServiceClass.ItemGetValues>));
        StoredStock.Add(ListValues[0]);
    }
}

private void setList(IEvent<GetLastValueCompletedEventArgs> ex)
{
    List.ItemsSource = StoredStock;
}


void Page_Loaded(object sender, RoutedEventArgs e)
{
    App.ViewModel.LoadData();
    List.ItemsSource = App.ViewModel.Items;
}

Как вы видите, я использую RX для вызова метода client_GetLastValueCompleted, добавляющего результат хранения во вспомогательную переменную (StoredStock). Затем обновите список в методе setList, но этот метод client_GetLastValueCompleted, что не очень хорошая идея, потому что мне нужно запускать этот метод только тогда, когда все запущенные GetLastValueAsync в foreach завершены. Вторая проблема: из-за асинхронного метода веб-службы StoredStock иногда имеет другой порядок, чем App.ViewModel.Items .

Любая хорошая идея, как сделать это правильно? С наилучшими пожеланиями,

Лукас


person sliwinski.lukas    schedule 18.06.2011    source источник


Ответы (2)


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

Если вы собираетесь использовать Rx, то у вас будет что-то вроде этого:

public Page()
{
    InitializeComponent();

    DataContext = App.ViewModel;

    this.Loaded += new RoutedEventHandler(Page_Loaded);
}

void Page_Loaded(object sender, RoutedEventArgs e)
{
    App.ViewModel.LoadData();

    var storedStock =
        new ObservableCollection<WebServiceClass.ItemGetValues>();  

    List.ItemsSource = storedStock;

    var values =
        Observable.Using<WebServiceClass.ItemGetValues, GPWWebservicePortTypeClient>
            (() => new GPWWebservicePortTypeClient(), ws =>
            {
                var clientGetLastValue = Observable
                    .FromAsyncPattern<string, GetLastValueResponse>
                    (ws.BeginGetLastValue, ws.EndGetLastValue);

                Func<string, WebServiceClass.ItemGetValues> deserializeFirst = r =>
                    ((List<WebServiceClass.ItemGetValues>)JsonConvert
                    .DeserializeObject(r,
                        typeof(List<WebServiceClass.ItemGetValues>)))
                    .First();

                return
                    from item in App.ViewModel.Items
                    from e in clientGetLastValue(item)
                    select deserializeFirst(e.Result);
            });

    values.Subscribe(storedStock.Add);
}

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


Я исправил код выше. Должен был вернуть запрос внутри вызова Using, а не назначать его values.


Я исправил вызов FromAsyncPattern, чтобы использовать правильные имена методов и тип возвращаемого значения из фактического эталонного класса веб-службы, отправленного по электронной почте.

Это должно выглядеть так:

Observable.FromAsyncPattern<string, GetLastValueResponse>
    (ws.BeginGetLastValue, ws.EndGetLastValue);
person Enigmativity    schedule 24.06.2011
comment
Большое спасибо за помощь, но не могли бы вы объяснить, что вы имеете в виду под ws.GetLastValueResult у моего клиента веб-сервиса нет этого метода -› private GPWWebservicePortTypeClient client = new GPWWebservicePortTypeClient(); ? - person sliwinski.lukas; 24.06.2011
comment
void client_GetLastValueCompleted(object sender, GetLastValueCompletedEventArgs e) Я пытаюсь использовать этот метод - написал вопрос, но vs говорит, что Not all code paths return a value in lambda expression of type System.Func<WP7GPW.GPWwebService.GPWWebservicePortTypeClient,System.IObservable<WP7GPW.WebServiceClass.ItemGetValues> - person sliwinski.lukas; 25.06.2011
comment
@Enigmativity, не могли бы вы помочь мне объяснить больше? - person sliwinski.lukas; 26.06.2011
comment
@sliwinski - я исправил пример кода - я не возвращал запрос в конце вызова Using. Что касается вызовов вашего метода в вашем классе GPWWebservicePortTypeClient, вы должны заметить, что я сказал, что вам нужно правильно указать имена методов. Вы должны заменить GetLastValueResult вызовом метода EndInvoke из вашего веб-сервиса. А поскольку у вас есть возможность вызывать службу асинхронно, Rx будет обрабатывать возвращаемое значение для вас, когда вы используете метод FromAsyncPattern, поэтому нет необходимости использовать обработчик событий GetLastValueCompleted. - person Enigmativity; 27.06.2011
comment
@Enigmativity Я думаю, что знаю, что вы имеете в виду под методом EndInvoke, но я не могу найти его в своем классе PortTypeClient, сгенерированном Visual Studio, когда я добавил ссылку на службу. Могу ли я сделать это самостоятельно, как действие или что-то в этом роде? Если хочешь, я могу выложить проект в сеть и ты увидишь, с чем именно у меня проблемы. - person sliwinski.lukas; 27.06.2011
comment
@sliwinski — пришлите мне электронное письмо на адрес code с моим именем пользователя точка com. - person Enigmativity; 28.06.2011
comment
@sliwinski - спасибо за код. Я обновил свой ответ соответственно. - person Enigmativity; 29.06.2011
comment
@Enigmativity Observable.FromAsyncPattern<string, GetLastValueResponse> (ws.BeginGetLastValue, ws.EndGetLastValue); ты уверен? Я опубликовал методы BeginGetLastValue и EndGetLastValue из веб-службы References, но тип результата EndGetLastValue — строка. Итак, я изменил его на Observable.FromAsyncPattern<string, string>(ws.BeginGetLastValue, ws.EndGetLastValue);, но у меня проблемы с типами с from e in clientGetLastValue(item), он должен быть clientGetLastValue(item.skrot) - аргумент вызова веб-сервиса с методом GetLastValue является строкой - person sliwinski.lukas; 29.06.2011
comment
@sliwinski - я только просмотрел ваш код в блокноте - моя среда не настроена для загрузки кода в VS. Я думал, что получил правильные методы и типы возвращаемых значений, но вы должны иметь возможность проверить это и внести необходимые изменения. Вам не должно быть слишком сложно заставить его работать. Дайте мне знать, как выглядел окончательный код. - person Enigmativity; 29.06.2011
comment
С вашим кодом у меня проблема с исключением нулевого указателя с func deserializeFirst. Посмотрите на мой первый отредактированный пост. Я делаю тот же код в другом стиле, и это работает, но когда я отлаживаю, я не знаю, почему, но у меня такое же исключение нулевого указателя ошибки с func deserializeFirst. Я отправляю вам письмо с проектом - должно работать (веб-сервис онлайн) - person sliwinski.lukas; 04.07.2011
comment
@sliwinski - Плохо так много редактировать свой вопрос. Если у вас есть дополнительный вопрос, вы должны опубликовать новый вопрос. Меняя вопрос, люди не могут использовать ваш вопрос и мой ответ, чтобы учиться. Я также оказал вам здесь большую помощь и не получил одобрения или принятого ответа, но, что еще хуже, изменив свой вопрос, вы аннулируете мой ответ и помощь. Пожалуйста, измените его обратно, отметьте мой ответ (если вы думаете, что я решил его) и опубликуйте новый вопрос. - person Enigmativity; 04.07.2011

Если вы новичок в C#, постарайтесь пока избегать RX. Это крутая технология, но если вы будете использовать ее без четкого понимания того, что происходит, она принесет больше проблем, чем решит.

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

person Sergey Aldoukhov    schedule 22.06.2011