WCF client proxy with Castle Dynamic Proxy

I’ve been doing a lot of work with WCF lately. It’s a great framework, and I really like it, but it has its drawbacks. First of all, it is overly complicated in certain places (security!), which makes it really hard to use sometimes. Its sheer size, makes it also hard to grasp. It has a lot of extensions points but the fact that you have to plug into them yourself adds to that complexity. It simply begs for good IoC integration.

You can partially alleviate that by using Castle WCF facility that lets you use IoC container to extend WCF, but it’s only half of the story. The other half is, that creators of WCF try very hard (and I mean, really very hard) not to allow you to do anything else than what they allow you to do. This is pretty frustrating at times, when you want to do some advanced things with it.

One such place is creation and usage of client side proxy. WCF, being all about SOAP messages is surprisingly heavily type based in this part, which does not leave you much flexibility here (this can be… hacked, but I’ll write about it in later post).

WCF client side proxies are remoting proxies. They are a thin layer around whole client WCF runtime and invocation pipeline. When you invoke a method on such proxy it gets intercepted by certain classes in WCF, based on the method you called and its parameters (and metadata on your ServiceContract type) a message is created and depending on various factors many other things happen under the cover (it’s pretty similar to how Dynamic Proxy’ interface proxies without target work).  The thing is, since it’s all private sealed and internal, you can’t really control any of it.

These two factors (strong coupling to CLR types and internal paranoia) made it very challenging when working on a feature I wanted to add to Castle WCF Facility – ability to invoke proxy methods asynchronously.

wcf_generate_async_operations

If you’re scratching your head thinking it’s hardly a new feature since you can do it already, let me explain you what I mean. Sure, you can select Generate asynchronous operations if you’re generating code for proxy, but this approach has some drawbacks. First of all, it uses code generation. Every time you change something you have to regenerate the code. Not to mention that this code is ugly as November night. The preferred approach is to factor out you contracts to separate assembly and to reuse them for both server and client (yes, this works only if both client and server use WCF).

In this case however you don’t get async methods. Turns out, you can do it without generated proxies, you have to create an async version of your interface though, and keep it in sync with the synchronous version. This is better since you control the code, you can use inheritance, it’s more compact than the generated version. You still have to create and maintain a type to satisfy weird desire of WCF to have types where type is not really needed.

Well, here’s a teaser for you:

castle_dp_WCF

I’ll blog about specifics of how the async stuff itself works in later post. Now I’ll explain how I got proxying stuff working. It’s also noteworthy that I did all that with public API only, no reflection, no IL generation – pure documented public API, which hopefully will pay back in this solution being quite stable.

To create the proxy, without codegen you use ChannelFactory<T> class, and its CreateChannel method. The method is virtual, so you can inherit from the class and get a chance to play with the proxy it creates before it’s passed the the caller.

Considering how remoting proxies are built, they consist of two parts: transparent proxy which is pure magic, and RealProxy which is just a normal CLR class. Drawing analogies to Dynamic Proxy library, RealProxy creates something similar to IInvocation, and passes it to RealProxy which acts as an IInterceptor.

I wanted to get hold of the RealProxy and swap transparent proxy with proxy generated by Dynamic Proxy. I also needed an adapter that would convert IInvocation to IMessage, which is what RealProxy uses.

Here’s the code that makes it happen

public override T CreateChannel(EndpointAddress address, Uri via)
{
    var channel = base.CreateChannel(address,via);
    IHasRealProxy proxy = new RealProxyWrapper(RemotingServices.GetRealProxy(channel));
    WCFInterceptor wcfInterceptor;
    ProxyGenerationOptions options = GetOptions(proxy, out wcfInterceptor);
    var target = _generator.CreateInterfaceProxyWithoutTarget(typeof(T), new[] { typeof(IEndAsyncCall) }, options, wcfInterceptor);
    return target as T;
}

Having transparent proxy, I use RemotingServices.GetRealProxy method to get its underlying RealProxy implementation. I then wrap the real proxy in Castle’s dynamic proxy and return it instead.

This may sound like it’s not a big deal but it has two significant implications: The whole operation is transparent to the RealProxy, the whole runtime underneath it, and the caller. Another thing – now you’re in control of the proxy. You can get into the execution pipeline and do the usual stuff dynamic proxy lets you do.

This is huge. This is what ultimately enables the async calls without having async type, which I’ll write about as soon as I clean up the code, which is now a mess. The code will probably get published as part of Castle WCF facility at some point later in time.

Technorati Tags: , ,

Comments

Joe Corba says:

Hi,

Did the code get published as part of Castle WCF facility?

Thanks