Monday, September 13, 2010

Silverlight - Using Fluent API to tie related async calls.

Introduction

In Silverlight all service calls are by default async calls. With ansync calls, you will be making a webservice call using one method and expects a call back in another method once you get a response from service. If you are using repository pattern you will be using same type of mechanism for communication between your view model and repositories.
In Async pattern there will be two related functions to accomplish a single task. One will initiate the task and another function will complete. Both these methods should work in tandem to accomplish single task.

And it will be highly error prone if you do not do proper event subscription & unsubscription. You also might want to take care of few common things like error handling, showing/hiding progress bar which will be common across all these calls. In this blog I will show you a interesting technique accomplishing same using elegant Fluent API solution.

Assume you have following repository class where you will define events once repositories webservice call complete it raises completed event, which will notify view model's completed event.
public class CustomerRepository

{

public event EventHandler<CustomEventArgs> GetCustomerNameCompleted;
public event EventHandler<CustomEventArgs> GetCustomerNameCompleted2;


public void GetCustomerName(string studyID)
{
WebServiceStub serviceStub = new WebServiceStub();
serviceStub.GetCustomerNameCompleted += (obj, args) =>
{

if (this.GetCustomerNameCompleted != null)
{
this.GetCustomerNameCompleted(this, args.GetCustomEventArgs());
}
};
serviceStub.GetCustomerNameByID(studyID);
}
public void GetCustomerName(string studyID, string Param1)
{
WebServiceStub serviceStub = new WebServiceStub();
serviceStub.GetCustomerNameCompleted2 += (obj, args) =>
{
if (this.GetCustomerNameCompleted2 != null)
{
this.GetCustomerNameCompleted2(this, args.GetCustomEventArgs());
}
};
serviceStub.GetCustomerName(studyID, Param1);
}

And in you View model


public void GetCustomers(int customerID)
{
repository.GetCustomerNameCompleted += repository_GetCustomerNameCompleted;

repository.GetCustomers(customerID)
}
void repository_GetCustomerNameCompleted(object sender, CustomEventArgs e)

{
repository.GetCustomerNameCompleted -= repository_GetCustomerNameCompleted;
}
You will be doing subscriptions and unsubscriptions throughout your silverlight ViewModels to repositories to fetch data. For each task you will have two methods in your view model.
You might be tempted to write completed method as anonymous, but it wont work as you have to unsubscribe once you are done. Otherwise subscriptions will keep on growing and you will get multiple callback for each call.

And if you forget to unsubscribe not only you will run into danger of memory leaks but buggy code. Instead of that if you can you use fluent API to make a call something as follows:

public void GetCustomer(string customerID)
{
StitchMethodFlow<string>

.Init
.WhenCalled(repository.GetCustomerName)
.WithParams(customerID)
.OnCompletionExecute((o,e)=>{//compelted;})
.CallBackSubscriptionProvider(repository.RegisterEventSubscription)
.StartExecution();
}

Above code looks simple, more maintainable, self explaining and code related to single task being done at single place not leaking to multiple methods. Now event subscription and Unsubscription are taken care by StitchMethodFlow.

You can download sample from here to see how it works. Demo is console application.