【问题标题】:Silverlight 4: REST API call data retrieval layer?Silverlight 4:REST API 调用数据检索层?
【发布时间】:2011-08-15 16:40:37
【问题描述】:

我正在使用 .NET 4 和 SL 4。 我想从我的 silverlight 页面后面的代码中抽象出我的 DAL 的数据检索部分。 理想情况下,放入自己的 DLL 作为我的 silverlight 应用程序和 REST API 调用之间的接口层。 我的意图不是使用 RIA 服务,因为我已经有一个现有的 DAL,它正在使用一个进行 REST API 调用的 DLL。

问题在于异步“WebClient”回调过程。 我知道我可以利用 WebClient 类进行 REST 调用,然后注册异步处理程序以简单地将调用的结果绑定到 UI。 但就我而言,我想将其抽象为它自己的 DLL。基本上....使其同步。

根据定义,异步调用的问题在于它不能立即直接返回某种类型的 IEnumerable。

谁能指出我正在做类似事情的示例/教程?

RIA 对单独的 DLL 进行方法调用以收集 IEnumerable 数据

该方法调用 REST API 来检索数据,然后将该 IEnumerable 返回给 RIA 并绑定到 UI。

【问题讨论】:

  • 将您的 UI 绑定到一个属性,该属性通过 ObservableCollection 返回您的 IEnumerable。这样,用户界面可以绑定到一个空列表,并且当数据以异步或同步方式返回时,只需适当地更新自身。

标签: c# silverlight data-binding rest


【解决方案1】:

将其归结为您实际要求的是能够对执行异步任务但仅在异步任务完成时返回的 API 进行同步调用。换一种说法,您希望将异步操作的开始和结束阶段重新组合回单个原子同步操作。

实现这一点的唯一方法是阻塞进行调用的线程,直到达到异步操作的结束阶段。出于多种原因,这不是一个好主意。

如果您认真使用 Silverlight,您必须接受它的异步特性并在该框架中使用,而不是试图将其强制返回到同步系统中。

将同步转换为异步

阅读blog,了解如何将同步代码转换为异步代码。现在让我们想象一下您的代码在名为DownloadYourDataObjects 的新DLL 中使用了一个同步方法,该方法具有这个虚构的签名:-

 public IEnumerable<YourDataObject> DownloadYourDataObjects(Uri source);

在内部,它使用 WebClient 从 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 的基本逻辑结构与原始同步版本相比不会有太大变化。

下面是您的 DLL 将提供的DownloadYourDataObjects 实现示例。

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

【讨论】:

    猜你喜欢
    • 2021-09-08
    • 2013-10-08
    • 2021-01-22
    • 1970-01-01
    • 2017-01-07
    • 1970-01-01
    • 2020-11-11
    • 2016-01-26
    • 1970-01-01
    相关资源
    最近更新 更多