So I have finally created an asynchronous wrapper for my web service assignment, allowing any method to called asynchronously. I'll give a quick demo of how it work:
1.
The Method Call
|
A method from within an asynchronous wrapper class. |
So, we start off with the wrapped method, in this case the
GetUserAsync method is going to allow us to retrieve a specific user asynchronously. The method makes a call to
DoAsync, inherited from the
AsyncCalls class (which will be discussed later), passing the
GetUser method (Converted into the right format, see number 2), the parameters it requires in an object array, and the name of the event.
2.
Converting the method format
|
The DoAsync method from the AsyncCalls class |
The reason the
GetUser need to be converted when being passed to
DoAsync, is because it does not match the
GenericAsyncDelegate signature.
|
The GenericAsyncDelegate signature for a method which takes an object[] a string and returns an AsyncData object |
So to convert
GetUser (A method that takes an int and returns a WebUser object) into the right format, I call the
ConvertFuncSingleArg method.
|
ConverFuncSingleArg method returning a method converted into a GenericAsyncDelegate. |
As you can see the method returns an
anonymous delegate in the form of a
GenericAsyncDelegate, using
ConvertResult to change the result of passed method into an object[], allowing it to be wrapped in a
AsyncData object. Because the methods return type is unknown until runtime, problems are caused if a collection is passed. A simple example of this would be if the return type was List<Object>, T would be assigned this type when the method is called, and all the checks will fail, as T is not an array and is not of type List<List<Object>>, so the method will return object[] {List<Object>}.
|
A method to convert the object passed into an object[] |
To solve the above problem, the generic type passed must be the return type in a non-collective form. This can be done using reflection, so I created a method as a layer to do this.
|
The middle layer of converting the return type. |
First of all, temp is set to the type of T, so if all tests fail, it is treated as the return type. Then I check if it is a type of array, if this is true then temp is set to the element type, otherwise treat it as a generic collection attempt to take it's generic type, if a generic type is found then set temp. In the above case Type.GetType will work as object is part of the referenced System namespace, but in cases where the type does not exist in a referenced namespace, the DLL needs to be loaded, and the type retrieved from it. Once the checks are complete the ConvertReturnType method needs to be called with temp as it's generic type, I use reflection to create the method, then invoke it with with MethodResult as a parameter.
3. The DoAsync Method
|
DoAsync method which sets up the process. |
The method starts by defining the callback delegate, this is the method is used to process the result of the async call, in this case the method will be called GenericAsyncCompleteCallback. Secondly creates a AsyncOperation object with no state, which is used to track and report the progress of the operation. Finally Istart the method (notice BeginInvoke being used not Invoke, as Invoke is synchronous), we pass the two GenericAsyncDelegate parameters, a reference to the callback, and the AsyncOperation object.
4. The Callback
|
The callback method. |
The callback method gets passed an object of IAsyncResult, which contains objects relating to the async call. I then extract the objects I want; the method doing the work and the state of the operation. I then create the
GenericAsyncCompletedEventArgs object (an extension of the
AsyncCompletedEventArgs class) containing the result of the async operation, which will be passed to the event handler. Finally we update the state of the
AsyncOperation to completed, specifying the operation complete method (which will be called after this) and the event arguments.
5.
Completed Call
|
The even called on completion. |
The only job of the OnGenericAsyncCompleted method is to fire the event handler, once the operation is complete.
|
The delegate for the event handler, and the event to be handled. |
6. The End
Now everything is complete I can show you the code in a working context.
|
A test situation |
Thank you for reading, my next post is most likely to be based on my Lisp assignment, hopefully you will enjoy it.
Liam