Silverlight 4: уровень извлечения данных вызова API REST? - PullRequest
1 голос
/ 29 апреля 2011

Я работаю в .NET 4 и SL 4. Я хочу абстрагировать часть поиска данных моего DAL из кода моей страницы Silverlight. Идеально в свою собственную DLL как интерфейсный слой между моим приложением silverlight и вызовами REST API. Мое намерение не состоит в том, чтобы использовать службы RIA, поскольку у меня уже есть существующий DAL, использующий DLL, которая выполняет вызовы REST API.

Проблема заключается в асинхронном процессе обратного вызова "WebClient". Я знаю, что могу использовать класс WebClient для выполнения вызова REST, а затем зарегистрировать асинхронный обработчик, чтобы просто связать результаты этого вызова с пользовательским интерфейсом. Но в моем случае я хочу абстрагировать это в свою собственную DLL. В основном .... делая это синхронно.

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

Может кто-нибудь указать мне пример / учебник, где делается нечто подобное?

RIA выполняет вызов метода для отдельной DLL для IEnumerable сбора данных

Этот метод выполняет вызов API REST для извлечения данных, а затем возвращает этот IEnumerable для RIA и привязывается к пользовательскому интерфейсу.

1 Ответ

2 голосов
/ 30 апреля 2011

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

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

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

Преобразование синхронного в асинхронное

Прочитайте этот блог о преобразовании синхронного кода в асинхронный код.Прочитав это, теперь давайте просто представим, что ваш код использует синхронный метод в вашей новой DLL с именем DownloadYourDataObjects, который имеет такую ​​воображаемую сигнатуру:REST базовый сервис и преобразует его в набор YourDataObject экземпляров.Мнимый синхронный код для отображения этого набора данных может быть: -

 private void btnLoadMyData_Click(object sender, RoutedEventArgs e)
 {
      try
      {
          LoadMyData();
      }
      catch (Exception err)
      {
          // Oops something bad happened show err.
      }
 }

 private void LoadMyData()
 {
      DataItemsListBox.ItemsSource = DownloadYourDataObjects(someUri);
 }

Поскольку Silverlight WebClient является асинхронным, нам необходимо преобразовать всю эту цепочку кода для работы в асинхронном режиме.

Используя AsyncOperationService из блога, нам сначала нужно преобразовать DownloadYourDataObjects, чтобы вместо него вернуть AsyncOperation.Он будет иметь такую ​​подпись (см. Ниже идею реализации): -

public AsyncOperation DownloadYourDataObjects(Uri source, Action<IEnumerable<YourDataObject>> returnResult);

Код использования будет выглядеть примерно так: -

 private void btnLoadMyData_Click(object sender, RoutedEventArgs e)
 {
      LoadMyData().Run(err =>
      {
          if (err != null)
          {
              // Oops something bad happened show err.
          }
      });
 }

 private IEnumerable<AsyncOperation> LoadMyData()
 {
      yield return DownloadYourDataObjects(someUri, result =>
      {
          DataItemsListBox.ItemsSource = result;
      });
 }

Это может выглядетьЛитт OTT, но на самом деле это не намного больше кода, чем оригинальная "синхронная" версия.В этом простом случае LoadMyData выполнялась только одна операция.Более сложная версия LoadMyData может содержать несколько других операций, которые также должны быть асинхронными.В таком случае эти операции будут просто другими yield точками в коде, базовая логическая структура LoadMyData не сильно изменится по сравнению с исходной синхронной версией.

Вот пример реализацииDownloadYourDataObjects, которую поставит ваша DLL.

 public AsyncOperation DownloadYourDataObjects(Uri source, Action<IEnumerable<YourDataObject>> returnResult)
 {
     return (completed) =>
     {
         WebClient client = new WebClient();
         client.DownloadStringCompleted += (s, args) =>
         {
             try
             {
                 returnResult(ConvertStringToYourDataObjects(args.Result));
                 completed(null);
             }
             catch (Exception err)
             {
                 completed(err);
             }
         };
         client.DownloadStringAsync(source);
     };
 }
...