A simple example of how to use the Reactive Extensions with Silverlight to process responses from web services.
One of the most useful tools that I have stumbled across in recent months has to be the Reactive Extensions (Rx) put out by Microsoft Labs. There are smarter people than me out there who have done a much better job of explaining WHAT Rx is (check a couple links in the Additional Reading section), so I wonâ€™t be stepping over into that realm, but rather I will be breaking down one way of utilizing Rx for use in Silverlight.
One word that is borderline synonymous with Silverlight is Asynchronous. Everything that you will end up doing in Silverlight is going to be Asynchronous, illustrated by the complete lack of IO blocks available from within your application.
From a UI standpoint, this is no problem. Once the application is downloaded and running, everything pretty much manages itself and you can go about your merry way. But what if you wanted to connect your application to, well, anything? Say you really wanted to get a little bit of real time information out of a database. This normally means delving into callback hell. Ok so maybe Iâ€™m being a little dramatic, but no one really enjoys writing up callback and handlers and what-not.
Enter the Reactive Extensions. Rx takes the brunt of the workload, and streamlines your coding, making for easier reading (once you understand what is going on). It is probably a good idea to have a solid understanding of lambda expressions and / or anonymous delegates. Iâ€™ve added a section at the end entitled Additional Reading, and added a link there.
This example requires that you have Visual Studio installed and functional, as well as Silverlight, AND the Rx Framework for Silverlight (link in the Additional Reading section). Also it would be a really good idea to have a web service either created and ready, or added to your project. I wonâ€™t be going into web services at all, as we will only be discussing what to do with the returned results.
|The first thing I did was create the UI. I just wanted a really simple form with a textbox and a button that looks like this:|
No trickery here. Just a textbox control and a button control placed in a stack panel. Basically we are going to use the button to kick off the data request which is going to in turn fill up our textbox.
On to the code. Create a new method that is hooked up to the Click event of the button. We are going to use the button click to initiate our call.
The very first thing that we have to do is define our â€œObservableâ€ object that will *react* to the events of the web service call. In Silverlight we only have access to the â€œObservable.FromEventâ€ method, which we can use like this:
var results = Observable.FromEvent<GetTopRevenueCompletedEventArgs>(
completed => client.GetTopRevenueCompleted += completed,
completed => client.GetTopRevenueCompleted -= completed )
This looks a little crazy, but it really isnâ€™t all that bad. In my example â€˜resultâ€™ is an IObservable object that is created â€œFromEventâ€, the event type being â€œGetTopRevenueCompletedEventArgsâ€, which is the completed event args of the method that Iâ€™m calling in my web service. The next two lines define the addition and removal of my GetTopRevenueCompleted method, which the observer is going to be listening to, and then the final line makes sure that the observer runs on the UI thread. Nothing really crazy here, weâ€™re just defining WHAT weâ€™re observing.
The next step is to actually tell it what to do:
var returnedResult = action.EventArgs.Result.Values;
foreach ( var item in returnedResult )
this.Results.Text += Environment.NewLine + item.Revenue;
e => this.Results.Text = “Error downloading…” + e.Message,
() => this.Results.Text += Environment.NewLine + “ALL DONE!!!” );
Now THIS is starting to look a little crazy. Whatâ€™s going on here? Once again, thereâ€™s no voodoo magic as long as you take a second to read whatâ€™s actually going on. What we have is a series of 3 lambdas that have a very specific function.
First off is â€œactionâ€: This is what happens when our â€œresultsâ€ object notices that our web service call has been completed. In my example I am connecting to an ASMX web service, and the return object (which becomes â€œactionâ€) is typed IEvent. Using this, I can create a new variable â€œreturnedResultsâ€ to which I assign the event args results, and from there process my returned array. This return is specific to my web service, and your results can be different.
Next lambda defined is â€œeâ€: this is simply â€œWhat do I do in the event of an error?â€, and I have it writing out an error message to my textbox.
And the final part, â€œ()â€ simply defines my completed action. This is simply â€œWhat do I do on completion?â€ In my case, all I wanted it to do was simply print out the final line to the textbox.
So now what do we do to make it make magic? Well, we simply call our service:
And there you have it. That is everything needed to call a web service, process, and then display the results, all asynchronously from Silverlight.
Reactive Extensions: http://msdn.microsoft.com/en-us/devlabs/ee794896.aspx
Lambda Expressions (XNA reference, but still applicable): http://nickgravelyn.com/2009/10/learning-lambda-expressions-for-xna-gs-developers/
Anonymous Delegates: http://geekswithblogs.net/joycsharp/archive/2008/02/15/simple-c-delegate-sample.aspx