Here I will illustrate how Reactive Extensions (Rx) can be applied to asynchronous calls to a WCF web service in a Silverlight application.
We start with a simple customer database consisting of a single table of first and last names.
ID First Last
1 Fred McFarlane
4 Susan McFarlane
6 David Green
10 Joe Bloggs
Then we set up a WCF service to return a collection of customers. I used LINQ to SQL to generate the CustomersDemo DataContext instance.
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(
RequirementsMode =
AspNetCompatibilityRequirementsMode.Allowed)
]
public class CustomersService
{
private string connection =
@"[My connection]";
[OperationContract]
public List<Customers> GetCustomers()
{
CustomersDemo db = new CustomersDemo(connection);
var customers = from customer in db.Customers
select customer;
return customers.ToList();
}
}
Asynchronous Access Without Rx
To consume the service in the Silverlight client…
Make the asynchronous call in the Page constructor.
public Page()
{
InitializeComponent();
CustomersServiceClient client =
new CustomersServiceClient();
client.GetCustomersCompleted +=
new EventHandler<GetCustomersCompletedEventArgs>(
client_GetCustomersCompleted
);
client.GetCustomersAsync();
}
Handle the completed event and display customers in a data grid.
void client_GetCustomersCompleted(
object sender,
GetCustomersCompletedEventArgs e
)
{
if (e.Error == null)
{
var customers = e.Result;
dg.ItemsSource = customers;
}
}
Results:
Asynchronous Access With Rx
In this case we dispense with the completed handler and centralise the code in the Page constructor. Instead of having a separate handler we create an IObservable from the GetCustomersCompleted event using the Observable.FromEvent method. The appended Take(1) is for returning a single value from the start of the observable sequence. It also implicitly unsubscribes the observer.
public Page()
{
InitializeComponent();
CustomersServiceClient client =
new CustomersServiceClient();
IObservable<IEvent<GetCustomersCompletedEventArgs>> observable =
Observable.FromEvent<GetCustomersCompletedEventArgs>(
client, "GetCustomersCompleted"
).Take(1);
observable.Subscribe(
e =>
{
if (e.EventArgs.Error == null)
{
var customers = e.EventArgs.Result;
dg.ItemsSource = customers;
}
});
client.GetCustomersAsync();
}
This produces the same results: