do { Engine.BlogAbout(".NET","Silverlight"); } while ( alive );  

Mark Monster

Mark Monster  

Using Function Pointers a la EventHandler<T> instead of return types

I did show it in my fourth article about Silverlight Networking, using a functionpointer in a call instead of a return type. This was to get the JavascriptWebResponse back asynchronous.

Working with the Silverlight Networking stack is only possible asynchronously. So we need to provide a callback function that get’s called after execution. All the Silverlight examples I’ve seen have this callback function in the User Interface. But what about all the classes that have their own responsibility that normally live in between the User Interface and the actual call to the Networking stack? I’m sure I don’t want to call the Networking stack right from the UI. I normally have at least one class between the UI and the Network call that does some transformation, preparation and other things. Let’s have a solution that I designed for Silverlight but also works within the full CLR.

The Example Situation

For this example I was working on a simple Delicious application that only shows the Tags that are within your Delicious account. I do have two responsibilities that are covered inside the Delicious application, namely the compilation of the JavascriptWebRequest (IDeliciousConnector) and the transformation of a xml-based string to real Tag objects (IDeliciousService). I won’t cover the the IWebRequestExecutor

The situation with return types

When we convert the example situation to a UML Sequence Diagram we get something like the following diagram.

Sequence Diagram with Return Types

 

The implementation with end-of-call function pointers

First of all I created the generic AsyncEventArgs class. It’s very easy and only has one property called Result that you can be typed exactly the same as you would normally type the return type. The looks of AsyncEventArgs is as follows.

1 public class AsyncEventArgs<T> : EventArgs 2 { 3 public T Result { get; set; } 4 }

Easy isn’t it? So instead of specifying a return type we now make every method of type void. And we add a callBack parameter to the method that’s an AsyncEventArgs EventHandler of the return type. At the end of the execution we call the callBack function with the typed AsyncEventArgs parameter.  This results in the following Sequence Diagram, no return messages but just only message calls. In effect the callBack is a function pointer parameter so the IDeliciousConnector doesn’t really know about the IDeliciousService, but it sort of looks like the diagram.

Sequence Diagram with end-of-call function pointers

The implementation of the interface is not that different, no voids anymore as you can see and a lot of callBack function pointers.

1 public interface IDeliciousService 2 { 3 void GetTags(EventHandler<AsyncEventArgs<IList<Tag>>> callBack); 4 } 5 6 public interface IDeliciousConnector 7 { 8 void GetTags(EventHandler<AsyncEventArgs<string>> callBack); 9 } 10 11 public interface IWebRequestExecutor 12 { 13 void Execute(JavascriptWebRequest request, 14 EventHandler<JavascriptResponseEventArgs> functionToCallOnResponse); 15 } 16

Let’s do some implementation.

Time for the method implementation

For the implementation I make much use of anonymous methods. As a start the implementation of IDeliciousConnector.GetTags. I started with a call to the webRequestExecutor which also expects a function parameter. I expect the WebResponse to be part of the eventArgs so if everything goes well I will be calling my callBack with only the WebResponse.Body as string in lines 16-18.

1 public void GetTags(EventHandler<AsyncEventArgs<string>> callBack) 2 { 3 var webRequest = new JavascriptWebRequest(); 4 //Some construction of the webRequest 5 webRequestExecutor.Execute( 6 webRequest, 7 (sender, eventArgs) => 8 { 9 if (eventArgs.WebResponse == null) 10 throw new Exception("Something went wrong. No WebResponse was available."); 11 if (eventArgs.WebResponse.StatusCode != "200") 12 throw new Exception( 13 string.Format("Expected statuscode 200 but was actually {0}", 14 eventArgs.WebResponse.StatusCode)); 15 if (callBack != null) 16 callBack(this, 17 new AsyncEventArgs<string> 18 {Result = eventArgs.WebResponse.Body}); 19 }); 20 }

Time for the implementation of the IDeliciousService.GetTags which will "return" a list of Tags. I used Linq2Xml for translating the Xml inside the string to a list of objects, see lines 7-16. And at the end I call the callBack function with the list of tags as result property in line 18.

1 public void GetTags(EventHandler<AsyncEventArgs<IList<Tag>>> callBack) 2 { 3 deliciousConnector.GetTags( 4 (sender, eventargs) => 5 { 6 string tagsXml = eventargs.Result; 7 XElement tagsElement = XElement.Load(new StringReader(tagsXml)); 8 IEnumerable<Tag> tags = 9 from tagElement in tagsElement.Descendants() 10 select new Tag 11 { 12 Count = 13 Convert.ToInt32( 14 tagElement.Attribute("count").Value), 15 Name = tagElement.Attribute("tag").Value 16 }; 17 if(callBack!=null) 18 callBack(this, new AsyncEventArgs<IList<Tag>> {Result = tags.ToList()}); 19 }); 20 }

I think this implementation is pretty clean, because almost everything happens inside of the anonymous method. There isn’t very much of magic glue, only an anonymous method with a generic AsyncEventArgs object. But it’s also important to test these kind of code. Let’s go over to the testing.

How to test this kind of code?

In the situation when we have just a return type we can easily assert if it’s the way we like it. But in the situation of async the Test method must be instructed to wait for the result to be available before testing the result. So the following code won’t work most of the time.

1 [Test] 2 public void ExpectReturnOf8TagsWrong() 3 { 4 IDeliciousService sut = SUT(); 5 IList<Tag> tags = null; 6 sut.GetTags((sender, eventargs) => 7 { 8 tags = eventargs.Result; 9 }); 10 Assert.AreEqual(8, tags.Count); 11 }

A better implementation will be by using a waitHandle, which will work.

1 [Test] 2 public void ExpectReturnOf8TagsGood() 3 { 4 IDeliciousService sut = SUT(); 5 IList<Tag> tags = null; 6 var waitHandle = new ManualResetEvent(false); 7 sut.GetTags((sender, eventargs) => 8 { 9 tags = eventargs.Result; 10 waitHandle.Set(); 11 }); 12 waitHandle.WaitOne(); 13 Assert.AreEqual(8, tags.Count); 14 }

I hope everyone thinks this article to be interesting. If anyone does have something to add I’d like to know. And don’t have any license for a real UML tool so I can’t help there are watermarks all over the images.

One Response to “Using Function Pointers a la EventHandler<T> instead of return types”

  1. Silverlight Cream for August 09, 2008 -- #341 Says:

    [...] sounds of it, it seems a bit of help might be in order, particularly from some knowledge experts! Using Function Pointers a la EventHandler instead of return types Mark also posted a nice article on using function pointers instead of return types and provides code [...]

Leave a Reply