Passing Code Blocks, That Doesn’t Sound Right?

I have been working on an application that makes heavy use of Windows Communication Foundation (WCF) proxies.  Do to an issue with how the Dispose method is implemented on the WCF client base class you aren’t supposed to use them in a ‘Using’ block.  To accommodate this what we encountered was the same try, catch ,catch,catch block around any instance of a WCF client proxy in our code.

The below example was common in our code:

Repeated WCF Client Wrapper
Repeated WCF Client Wrapper

What we realized was that we could use generics and the fact that all WCF clients inherit from the same base classes and implement the same base interfaces to pull the common init and clean up code out into one place.  Luckily for us the ‘Abort’ and ‘Close’ methods are both implemented by the ‘ICommunicationObject’ interface and all WCF clients implement it.   Just like the ‘Using’ statement wraps a try/finally block around a code block we want to wrap our try/catch/catch around a code block.

Generics allows us to wrap a code block.  We can create a generic method that takes a parameter of our client type as an argument,  does our init and cleanup against the argument as an ‘ICommunicationObject’, then passes the argument to a code block defined to take a parameter of our generic type.  The wrapper looks something like the below:

newway2
WCF Client Wrapper

Using generics we can even constrain our generic method so it will only take somethign that implements ‘ICommunicationObject’ , we can also do the same thing to the delegate that defines our code block parameter.   What worked out really nice about this approach is that this cleanup code that was duplicated in several places is now in one place.  If we change how we init or clean up our WCF clients we have one spot to update.  Also, the code needed to call a client is drastically reduced:

New WCF Client Call
New WCF Client Call

It take a little getting used to.  Something does feel a little odd about passing a code block as a parameter.  What is really going on here is you are creating a macro.  The compiled IL really duplicates the code, but you don’t have to.  The nice thing about this being a macro is you can use variables declared outside the code block inside the code block and things still work:

Variable Declared Outside Block
Variable Declared Outside Block

What is interesting about this is the inversion of the normal mechanism of isolating code  for reuse.  Normally you refactor our common code into separate methods, or code blocks, so they can be called from different places.  Here it’s the code block that is changing and being passed into the reusable wrapper.  This has been very helpful so far, I’m interested to see what downsides pop up.

Leave a Reply

Your email address will not be published. Required fields are marked *