2010-03-19 28 views
5

我在.NET中编写的用于创建REST调用的大部分代码都是同步的。由于Windows Phone上的Silverlight仅支持异步WebClient和HttpWebRequest调用,因此我想知道一个良好的异步模式适用于公开可进行REST调用的方法的类。顺序WebClient请求的良好异步模式

例如,我有一个应用程序需要执行以下操作。

  1. 登录并获得令牌
  2. 从#1使用令牌,获得专辑
  3. 从#1使用令牌的名单得到类别

我的类公开名单几种方法:

  1. 登录()
  2. GetAlbums()
  3. GetCategories()

因为每个方法需要使用异步调用什么,我需要做的是基本阻止呼叫登录,直到它返回,这样我可以调用GetAlbums()来调用Web客户端。

什么是在我的课中揭示这些方法的好方法?

回答

3

这实际上取决于你想用这个信息做什么。例如如果您正试图以显示专辑/类别等的列表,来模拟这一方法是

  1. 有它实现INotifyPropertyChanged接口的一个或多个类别,并用来为您的视图的数据源(以新的PhoneListApplication中的Models文件夹下的文件为例)
  2. 启动异步操作以登录并获取令牌,使异步方法的回调为您存储令牌并调用将启动异步的函数操作来获取相册和类别的列表。
  3. 用于异步操作以获取相册/类别列表的回调可以更新ObservableList(通过向其添加项目)。我想成像你有一个类的专辑和类别,每个都有一个可观察的列表。无论如何,一旦你完成添加,只需调用NotifyPropertyChanged与您更改的属性的名称,并且您的数据应该显示。

有一个明显的问题,您想等待,直到您收到通过网络回来的东西(例如,如果您想保留登录页面,直到您知道您已成功通过身份验证) 。在这种情况下,您可以更改异步回调中的页面。

你当然也可以做更有趣的事情,并有一个线程等待由异步回调设置的事件。我建议不要让UI线程这样做,因为它限制了你有超时等事情的能力,而且通常很麻烦。

7

你可能需要看看反应器(Rx)框架扩展:

http://www.leading-edge-dev.de/?p=501

http://themechanicalbride.blogspot.com/2009/07/introducing-rx-linq-to-events.html

[编辑:哦 - 找到一个很好的链接:] http://rxwiki.wikidot.com/101samples

他们提供一种“顺序”事件的方式,仅在符合某些条件时才起作用 - 例如,假设您有一个方法“AuthenticationResult Authenticate(string user,string pass)”

你可以这样做:

var foo = Observable.FromAsyncPattern<string, string, AuthenticationResult> 
    (client.BeginAuthenticate, client.EndAuthenticate); 
var bar = foo("username","password"); 
var result = bar.First(); 

有效地将异步方法,以一个同步。你可以扩展到包括“链接”:

var bar = foo("username", "password") 
    .Then(authresult => DoSomethingWithResult(authresult)); 

Neat stuff。 :)

1

我们与这个样子的所有异步函数签名写我们的客户端服务层:

public void MyFunction(
    ArtType arg, 
    Action<ReturnType> success, 
    Action<FailureType> failure); 

服务代码没有一个异步调用Web服务,而返回时,它会调用成功回调(如果调用成功)以及失败回调(如果出现故障/异常)。然后调用代码有点看起来是这样的:

MyServiceInstance.MyFunction(
    blahVar, 
    returnVal => UIInvoker.Invoke(() => 
    { 
     //some success code here 
    }), 
    fault => UIInvoker.Invoke(() => 
    { 
     //some fault handling code here 
    })); 

(UIInvoker仅仅是一种实用工具,分派回从后台线程的用户界面。)

1

我把东西在一起更流畅一点。

Restful-Silverlight是我创建的一个库,用于帮助Silverlight和WP7。

我已经包含下面的代码,以显示如何使用该库从Twitter检索推文。从Twitter雷斯特夫尔-Silverlight的检索鸣叫

示例用法:

 

//silverlight 4 usage 
List<string> tweets = new List<string>(); 
var baseUri = "http://search.twitter.com/"; 

//new up asyncdelegation 
var restFacilitator = new RestFacilitator(); 
var restService = new RestService(restFacilitator, baseUri); 
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri); 

//tell async delegation to perform an HTTP/GET against a URI and return a dynamic type 
asyncDelegation.Get<dynamic>(new { url = "search.json", q = "#haiku" }) 
    //when the HTTP/GET is performed, execute the following lambda against the result set. 
    .WhenFinished(
    result => 
    { 
     textBlockTweets.Text = ""; 
     //the json object returned by twitter contains a enumerable collection called results 
     tweets = (result.results as IEnumerable).Select(s => s.text as string).ToList(); 
     foreach (string tweet in tweets) 
     { 
      textBlockTweets.Text += 
      HttpUtility.HtmlDecode(tweet) + 
      Environment.NewLine + 
      Environment.NewLine; 
     } 
    }); 

asyncDelegation.Go(); 

//wp7 usage 
var baseUri = "http://search.twitter.com/"; 
var restFacilitator = new RestFacilitator(); 
var restService = new RestService(restFacilitator, baseUri); 
var asyncDelegation = new AsyncDelegation(restFacilitator, restService, baseUri); 

asyncDelegation.Get<Dictionary<string, object>>(new { url = "search.json", q = "#haiku" }) 
       .WhenFinished(
       result => 
       { 
        List<string> tweets = new List(); 
        textBlockTweets.Text = ""; 
        foreach (var tweetObject in result["results"].ToDictionaryArray()) 
        { 
         textBlockTweets.Text += 
          HttpUtility.HtmlDecode(tweetObject["text"].ToString()) + 
          Environment.NewLine + 
          Environment.NewLine; 
        } 
       }); 

asyncDelegation.Go(); 
 
+1

貌似REF URL以上下https://github.com/amirrajan/Restful现在 – Stonetip

+0

Silverlight的位已经被移动到轧制旧标签 – Amir