WCF client proxy with Castle Dynamic Proxy

I’ve been doing a lot of work with WCF lately. It’s a great frame­work, and I really like it, but it has its draw­backs. First of all, it is overly com­pli­cated in cer­tain places (secu­rity!), which makes it really hard to use some­times. Its sheer size, makes it also hard to grasp. It has a lot of exten­sions points but the fact that you have to plug into them your­self adds to that com­plex­ity. It sim­ply begs for good IoC integration.

You can par­tially alle­vi­ate that by using Cas­tle WCF facil­ity that lets you use IoC con­tainer to extend WCF, but it’s only half of the story. The other half is, that cre­ators of WCF try very hard (and I mean, really very hard) not to allow you to do any­thing else than what they allow you to do. This is pretty frus­trat­ing at times, when you want to do some advanced things with it.

One such place is cre­ation and usage of client side proxy. WCF, being all about SOAP mes­sages is sur­pris­ingly heav­ily type based in this part, which does not leave you much flex­i­bil­ity here (this can be… hacked, but I’ll write about it in later post).

WCF client side prox­ies are remot­ing prox­ies. They are a thin layer around whole client WCF run­time and invo­ca­tion pipeline. When you invoke a method on such proxy it gets inter­cepted by cer­tain classes in WCF, based on the method you called and its para­me­ters (and meta­data on your Ser­vice­Con­tract type) a mes­sage is cre­ated and depend­ing on var­i­ous fac­tors many other things hap­pen under the cover (it’s pretty sim­i­lar to how Dynamic Proxy’ inter­face prox­ies with­out tar­get work).  The thing is, since it’s all pri­vate sealed and inter­nal, you can’t really con­trol any of it.

These two fac­tors (strong cou­pling to CLR types and inter­nal para­noia) made it very chal­leng­ing when work­ing on a fea­ture I wanted to add to Cas­tle WCF Facil­ity – abil­ity to invoke proxy meth­ods asynchronously.

wcf_generate_async_operations

If you’re scratch­ing your head think­ing it’s hardly a new fea­ture since you can do it already, let me explain you what I mean. Sure, you can select Gen­er­ate asyn­chro­nous oper­a­tions if you’re gen­er­at­ing code for proxy, but this approach has some draw­backs. First of all, it uses code gen­er­a­tion. Every time you change some­thing you have to regen­er­ate the code. Not to men­tion that this code is ugly as Novem­ber night. The pre­ferred approach is to fac­tor out you con­tracts to sep­a­rate assem­bly and to reuse them for both server and client (yes, this works only if both client and server use WCF).

In this case how­ever you don’t get async meth­ods. Turns out, you can do it with­out gen­er­ated prox­ies, you have to cre­ate an async ver­sion of your inter­face though, and keep it in sync with the syn­chro­nous ver­sion. This is bet­ter since you con­trol the code, you can use inher­i­tance, it’s more com­pact than the gen­er­ated ver­sion. You still have to cre­ate and main­tain a type to sat­isfy 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 prox­y­ing stuff work­ing. It’s also note­wor­thy that I did all that with pub­lic API only, no reflec­tion, no IL gen­er­a­tion – pure doc­u­mented pub­lic API, which hope­fully will pay back in this solu­tion being quite stable.

To cre­ate the proxy, with­out code­gen you use ChannelFactory<T> class, and its Cre­at­e­Chan­nel method. The method is vir­tual, so you can inherit from the class and get a chance to play with the proxy it cre­ates before it’s passed the the caller.

Con­sid­er­ing how remot­ing prox­ies are built, they con­sist of two parts: trans­par­ent proxy which is pure magic, and Real­Proxy which is just a nor­mal CLR class. Draw­ing analo­gies to Dynamic Proxy library, Real­Proxy cre­ates some­thing sim­i­lar to IIn­vo­ca­tion, and passes it to Real­Proxy which acts as an IInterceptor.

I wanted to get hold of the Real­Proxy and swap trans­par­ent proxy with proxy gen­er­ated by Dynamic Proxy. I also needed an adapter that would con­vert IIn­vo­ca­tion to IMes­sage, which is what Real­Proxy 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;
}

Hav­ing trans­par­ent proxy, I use RemotingServices.GetRealProxy method to get its under­ly­ing Real­Proxy imple­men­ta­tion. 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 sig­nif­i­cant impli­ca­tions: The whole oper­a­tion is trans­par­ent to the Real­Proxy, the whole run­time under­neath it, and the caller. Another thing – now you’re in con­trol of the proxy. You can get into the exe­cu­tion pipeline and do the usual stuff dynamic proxy lets you do.

This is huge. This is what ulti­mately enables the async calls with­out hav­ing async type, which I’ll write about as soon as I clean up the code, which is now a mess. The code will prob­a­bly get pub­lished as part of Cas­tle WCF facil­ity at some point later in time.

Tech­no­rati Tags: , ,