Dynamically Generated WCF Proxies

Most programmers that start with Windows Communication Foundation (WCF) use the provided samples and tutorials from Microsoft. All these…

Dynamically Generated WCF Proxies
Photo by Blake Connally on Unsplash

Most programmers that start with Windows Communication Foundation (WCF) use the provided samples and tutorials from Microsoft. All these samples are based on static generated service references or proxies. When you want to connect from a client to a server, you create a reference from the client to the server project using the Visual Studio Add Service Reference function. Visual Studio then connects to the server, extracts the metadata from the server, and generates a proxy. The client uses this proxy to connect and call methods on the server.

Most programmers don’t know that you can also generate this WCF proxy dynamically. This dynamic generation of a proxy has a lot of advantages.

Background

As we all know, sometimes during development, the interface of a service change. The same is possible for the configuration of a service; for example, the port number on which a service listens to changes. Now, say that a developer changes the interface or the configuration of a service, and somehow he or she forgets to change the client (this has happened to me more than once). With a statically generated proxy, you would notice the error late in the development cycle, probably during the first test.

This scenario has happened to me many times and led me to think that there had to be another way. Wouldn’t it be much better to tackle this problem during compilation on your local workstation or during a build on your build server? With a dynamically generated proxy, this is possible.

Structuring Your Assemblies

To be able to use the dynamic proxy and its advantages, you have to structure your assemblies or classes somewhat different. Both the client and the server reference and use a separate assembly that contains the interface and the configuration of the WCF service. The picture below shows the idea:

The assembly called “Interface + Configuration” contains the WCF configuration of the server, including the interface itself. By structuring your assemblies this way, it is not possible to forget changing the client when the interface changes. It just won’t compile!

Using the Code

The source code contains three assemblies, the server, the client, and the interface/configuration assembly. These are contained within a single Visual Studio 2008 solution. When you run the application, both the server and the client will start. The client sends a couple of messages to the server.

Generating the dynamic proxy using WCF is not difficult, the ChannelFactory from WCF makes it possible. The source code to generate a dynamic proxy is shown below.

The Client

ChannelFactory uses the interface IMessageSender to create a channel through the method CreateChannel. The interface IMessageSender and Configuration are both from the shared assembly.

The server side also uses this information from the Configuration class. It creates a new ServiceHost and listens on the Uri from the Configuration.

The Server

The method Configuration.CreateBinding() creates the binding. This method returns an instance of a specific binding which is configured in the Configuration class. If you change the binding of the server, for example, from HTTP to TCP, both the client and the server will automatically use it.

Points of Interest

This solution is not rocket science, but it has helped me and my company save time. When someone forgets to change the client after an interface change, the solution won’t compile. This way, it fails fast, which is a good thing. Another advantage is that you could stop publishing metadata of your service, this will increase the security of your service.

Central Binding Configuration

Together with the configuration, the binding is also configured centrally in the configuration assembly. This enables you to configure the binding for the client as well as for the server. You could, for example, set the MaxReceivedMessageSize and the ReceiveTimeout, which should be set for the client as for the server. By centralizing the configuration, this can now be done in a single place instead of two or more configuration files. The code below shows an example of how to do this.

Further Extension of the Configuration

By standardizing the configuration of your services, it is possible to extend this even further. For example, you could create a standard base class or interface for all your configurations. This standardization makes it possible to extract information from your configuration, for example, documentation. This would enable automatic documentation creation from your configuration classes. The result, complete up to date documentation of all your services. A good way to start is to define an interface with methods for all the attributes to document. See the code below for an example.

Using Callbacks

Callbacks are possible using this solution. When using callbacks, the ChannelFactory used in the client should be changed to a DuplexChannelFactory. The constructor of a DuplexChannelFactory expects an instance where the callback method(s) can be called by the server. Also, the client should call the subscribe and unsubscribe methods to add the callback method. See the code below for an example. The provided source code in the download includes an example using callbacks.

Disadvantages

This solution has its disadvantages. It works only if you control both sides of the wire. If you publish the service for users outside your company, it’s a different scenario. You could publish the interface and configuration assembly, but I think that enabling meta-data on your service would be easier for such a situation.


Originally published at http://www.simpletechture.nl/blog/2011/generatewcfproxy/.