From a client application I am sending a request/transaction (containing an operation to perform (and parameters) + transactionID) to a remote queue. The remote server dequeue the request at some point and takes some time to process it.
Once it is done processing it, it sends a reponse on the client queue (containing the applicative response + the transactionID) … so this is a totally “disconnected” communication mode, the only way that the client can map the response to the request is via the transactionID.
Message response is dequeued on client side, and matched with the original request (based on the transactionID).
What I am doing right now is that when the client post the request to the server queue, it adds a callback to a dictionnary keeping transactionId and callback (delegate). This is a Dictionary<int, object> mapping a transactionId back to a callback to call with the result of the operation.
The callbacks/delegates are stored as object due to the fact that depending of the request, the callback delegate signature is different (for example a response may return a List<string> whereas another response may return an int).
When the client queue dequeues a response, it knows the type of the response (and therefore the corresponding signature of the callback), therefore it gets the callback from the dictionary, based on the transactionID. It then casts the object back to the corresponding delegate type and invoke the callback.
I find this approach not very “sexy” but I do not really see another way of performing such a task.
Is there any better way of performing this ?
If the problem is not clear enough, please let me know and will clarify with some edits.
You might find Reactive Extensions a handy tool for that kind of messaging.
First, make all your responses implement some interface or base class, like IMessage. Each kind of response should be encapsulated in a separate class like here
Then make your message queue implement
IObservable<IMessage>. Reactive extensions provides a ready to use implementation calledSubject<T>, you might want to wrap it or something.Observable implements a
Subscribe(IObserver<IMessage> observer)method which stores observers somewhere in an internal list. When a new response arrives anOnNext(IMessage message)method is called on each subscribed observer.Finally, your response handling registration code might look like:
That will register callback for a message of type UserListMessage with given transaction ID.
Probably you will also want to unsubscribe somewhere. That will be:
That was a brief sample how that would look like with Rx. Now go and find some more detailed tutorial.