Typically, when you need WCF client proxies, you use the svcutil.exe
tool or the respective code generation
functionality from inside Visual Studio (“Add Service Reference …”). This approach might be suitable for a
setup where server, i.e. its contract, and client are not in the same project or company – that is where
the service contract only changes where seldom.
On the other hand, if you use WCF merely as the communication infrastructure for your application, or where
you actually have a contracts assembly at hand that you can reuse, generating the client proxies can be a pain.
The svcutil.exe
solution doesn’t lend itself very well to be done during a build, because it would first require
you to startup the service so that you can contact it to generate the proxies.
In the project I’m working in now for a couple of years, we have thus started with a different solution from the beginning. We generate the client proxies during runtime using dynamic code generation. Now, when I say we generate the proxys, what I really mean is, we generate the CLR type for the proxy. That can happen by a couple of means really:
Now, if you think that sounds pretty expensive performance wise, you are not mistaken. Naturally, the first approach
using CodeDom and actually firing up the compiler (CSC.EXE
) in the background is way more expensive than the others,
but all have their ramp up cost to generate the proxy. So it is advisable to cache the resulting generate System.Type
instance for further use.
Note that in an actual scenario the cost to generate the proxy is normally totally dwarfed by the actual overhead of doing a remote call (including marshalling of real world payload, network latency, etc.).
For our project we choose the third approach for being the fastest and also giving us the best flexibility of actually generating the proxy. Of course, it does require knowledge of the Intermediate Language (IL) to some extent, but it does pay off in the end.
Pro debugging tip: write the code as you want it to be generated in C#, compile it, then view it with a dissembler
(ILDasm.exe
, dotPeek, etc.) to see how the IL you want to really generate should look like. Also, if you get runtime
errors about your generated type during runtime, view that generated code with a Reflector or such to see the C#
code that you actually would have generated.
Ok, now into the details.
We’ll start top down, with the final implementation on the client, i.e. how to use the whole machinery. Actually, that point is also the most important, as the whole point of the endeavor is ease of use. What you can’t see in the following source code is, that there is no special magic going on during the build, apart from the client (project) needing a reference to the contracts (assemblies) that it wants to use. So, without further ado here is our fabulous service contract:
Using it from the client then basically looks like this:
Let’s dissect that snippet:
We use the client in a using-Scope to properly dispose the client, i.e. close the channel after we are done using it.
Note: Don’t do this with the proxies generated by svcutil.exe
et. Al. The System.ServiceModel.ClientBase<>
class has a
bug in the Dispose operation that basically can hide exceptions thrown from inside the using block.
For details see http://www.codeproject.com/Tips/197531/Do-not-use-using-for-WCF-Clients, or just search the Web.
There are multiple of references. When generating our proxy type we fix that issue while we’re at it. More on that later.
The ServiceClient<>
class is the wrapper for our generated proxy and the “entry point” to whole machinery.
That is, you will never really encounter the generated type in code - Think about it. How would you?
It only ever exists during runtime so you cannot possible reference it in the source, during compile time.
The EndpointNameFromAppConfig is exactly this – see your WCF tutorials, etc. for detail.
Note that ServiceClient<>
provides some additional constructors to work without app.config
declared endpoints.
Call the service operations of choice by means of delegating through the Contract property.
I.e. the Contract property has the type of the service contract you instantiated the type with;
ICalculator
in our example.
I will not show the code for the service side here, because it is – as it should be – totally unaffected by any of this.
Let’s dig into the implementation of ServiceClient<>
. Basically, it mimics the System.ServiceModel.ClientBase<>
type by
providing the same set of constructors that it does. As a base class it uses the non-template, abstract, ServiceClientBase
class.
ServiceClientBase
is responsible for dealing with the actual proxy type generation, if it must.
That is, once a proxy for certain service contract has been generated it will cache it to reuse it later.
Ultimately, if a respective proxy type does not yet exist, it will use the ProxyGenerator
-class to create one matching
the service contract in question.
It does that by generating a method implementation for each method attributed with [OperationContract]
in the service contract type.
That sounds easier than it is, because you have to watch out for the peculiarities of async operations, one way operations,
inherited service contracts, generating constructors, etc. But in the end it is melange of reading the service contract type
with reflection and generating appropriate proxy code using reflection emit.
The main workhorse method of ProxyGenerator actually shows that overall processing quite nicely:
Actually, posting all of the code here would be way too much content, so as an example of how the code looks,
I will show the code that generates the “exception-safe” Dispose method. The one the original ClientBase<>
from WCF fails to provide properly.
The real issue with ClientBase<>.Dispose()
is, that it unconditionally calls Close()
, whereas it should
only do so, if the channel is not already faulted. Because if it is, the additional call to Close()
will raise
another exception, hiding the one that caused the channel to fault in the first place. A proper implementation
of Dispose()
would thus look like this (expressed in C#):
And here is the code that does the same in IL, i.e. with Reflection.Emit:
Essentially, we start of by getting reference to the methods, properties, etc. that we need to call from IL. Then we write the actual logic as IL instructions.
All code for the proxy generation is provided in the WcfProxyHelper assembly. A test client and server is provided as well.