2010-03-19 12 views
5

La mayor parte del código que he escrito en .NET para hacer llamadas REST ha sido sincrónico. Como Silverlight en Windows Phone solo admite llamadas Async WebClient y HttpWebRequest, me preguntaba qué buen patrón de sincronización es para una clase que expone métodos que realizan llamadas REST.Patrón Good Async para solicitudes secuenciales de WebClient

Por ejemplo, tengo una aplicación que necesita hacer lo siguiente.

  1. de sesión y obtener token de
  2. mediante el testigo de # 1, obtener una lista de álbumes
  3. mediante el testigo de # 1 obtener una lista de categorías
  4. etc

mis expone clase algunos métodos:

  1. Login()
  2. GetAlbums()
  3. GetCategories()

ya que cada método tiene que llamar al cliente Web utilizando asíncrono llama lo que tengo que hacer es llamar a bloquear esencialmente de sesión hasta que se vuelve de modo que pueda llamar GetAlbums().

¿Cuál es una buena manera de hacer esto en mi clase que expone esos métodos?

Respuesta

3

Realmente depende de lo que quieras hacer con esta información. Si por ejemplo usted está tratando de mostrar la lista de álbumes/categorias, etc, una forma de modelar esto sería

  1. tener una o más clases que implementa la interfaz INotifyPropertyChanged, y se utilizan como fuentes de datos para sus puntos de vista (mira los archivos debajo de la carpeta Models en una nueva PhoneListApplication para un ejemplo)
  2. Inicia una operación asíncrona para iniciar sesión y obtener el token, haz que la devolución de llamada del método asincrónico almacene el token y llama a una función que iniciará una asincrónica operación para obtener una lista de álbumes y categorías.
  3. La devolución de llamada para la operación asincrónica para obtener una lista de álbumes/categorías puede actualizar una Lista observable (agregando elementos a ella). Imaginé que tienes una clase para álbumes y categorías, cada una con una lista observable. De todos modos, una vez que haya terminado de agregar, simplemente llame a NotifyPropertyChanged con el nombre de la propiedad que ha cambiado, y sus datos deberían aparecer.

Existe un problema obvio en casos en los que desea esperar y no continuar hasta que reciba algo en la red (por ejemplo, si desea mantener la página de inicio de sesión hasta que sepa que se ha autenticado correctamente) . En este caso, puede cambiar la página en la devolución de llamada asíncrona.

Es obvio que también puedes hacer algo más elegante y tener un hilo de espera para un evento establecido por la devolución de llamada asíncrona. Recomiendo que el hilo de la interfaz de usuario no haga esto, ya que limita su capacidad de tener cosas como tiempos de espera, y generalmente es muy desordenado.

7

Es posible echar un vistazo a la reactiva (Rx) extensiones marco:

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

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

[editar: ooh - encontrado un buen enlace:] http://rxwiki.wikidot.com/101samples

Ellos proporcionar una forma de "secuenciar" eventos, actuando solo bajo ciertas condiciones cumplidas, por ejemplo, supongamos que tiene un método "AuthenticationResult Authenticate (string user, string pass)"

Se podría hacer algo como:

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

convirtiendo efectivamente un método asíncrono a una sincrónica. Puede extender esto para incluir "encadenamiento":

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

Cosas aseadas. :)

1

Escribimos nuestra capa de servicio del lado del cliente con todas las firmas de función asíncrona que se ven así:

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

El código de servicio hace un llamada asincrónica al servicio web, y cuando eso vuelve llama a la éxito de devolución de llamada si la llamada fue exitosa, y la devolución de llamada fallida si hubo una falla/excepción. A continuación, el código que llama a poco se parece a esto:

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

(UIInvoker es sólo una utilidad que envía de nuevo a la interfaz de usuario desde un subproceso en segundo plano.)

1

que armar algo que es un poco más fluido.

Restful-Silverlight es una biblioteca que he creado para ayudar con Silverlight y WP7.

He incluido el código a continuación para mostrar cómo puede usar la biblioteca para recuperar tweets de Twitter.

Ejemplo de uso de Silverlight reparador-tweets de recuperar de Twitter:

 

//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

Parece url ref anterior está enrollada debajo https://github.com/amirrajan/Restful ahora – Stonetip

+0

Los bits de Silverlight se han movido en una etiqueta heredada – Amir

Cuestiones relacionadas