One of the way tuning performance of WCF services is to use WCF proxy caching. There has been a long discussion on this subject. Bottom line is FW 4.0 supports caching proxies with some conditions, you may see details here.
In order to call WCF services, we need a proxy first. We can create one either at design time or run time. Let’s see each one
Design Time Proxy Creation
Once the services are ready and in run state, you can utilize svcutil.exe or Visual Studio’ service reference features to create a proxy. For example, in my prior post here, when added a service reference to the project, VS 2010 creates proxy and contracts classes behind as below:
Notice that it is using Channel property of ClientBase<T> abstract class and here we don’t own this channel or its lifetime, once the call is done, proxy is gone (like a lyric). After that, I can call the proxy as simple as below from my unit test method:
4://TargetService.IService1 proxy = new TargetService.Service1Client("targetEP");
5: TargetService.IService1 proxy = new TargetService.Service1Client("routerEP");
16: System.ServiceModel.Configuration.ServiceElement el = coll[i];
19: epa = new EndpointAddress(el.Endpoints.Address.ToString());
20: strBinding = el.Endpoints.Binding;
25: binding = new BasicHttpBinding();
28: binding = new WSHttpBinding();
31: binding = new NetTcpBinding();
34: binding = new NetMsmqBinding();
37:thrownew NotImplementedException(strBinding + " not implemented.");
44:returnnew ChannelFactory<IType>(binding, epa);
As we know, WCF clients communicate to services based on contracts (hand-shake) and that is the minimal piece to be shared between publisher and consumer. Here, what we do is to make an assembly including both contracts and proxy creation class(es) and add reference to it from the client.
Pros and cons of using Run time proxy
No need to go through refreshing service references if contract or address changed
You have your own transparent proxy, you can control it
All is implemented in an assembly or assemblies, easy to share
Service calls are per service contracts
In either way, generating a proxy for each call is an expensive operation (constructing channel, opening it, closing, etc.). Instead we can cache each channel once they are created and utilize them for the next calls, as pointed out earlier, there are some cases, caching is already supported within the framework.
Above, the 2nd option, generating proxy at run time is not calling Open() explicitly, so we know it is not going to use caching by default. Remember we are to cache ChannelFactory that the proxy is created based on. Here is a proxy manager class which adds or removes the underline ChannelFactory to/from dictionary object.
3:internalstatic ConcurrentDictionary<string, ChannelFactory<IType>> proxies = new ConcurrentDictionary<string, ChannelFactory<IType>>();
5:internalstatic IType GetProxy(string key)
7:return proxies.GetOrAdd(key, m => ProxyFactory<IType>.Create()).CreateChannel();
10:internalstaticbool RemoveProxy(string key)
12: ChannelFactory<IType> proxy;
13:return proxies.TryRemove(key, out proxy);
Hope it suits your case.
WCF proxies are expensive to generate/dispose. FW 4.0 supports caching proxies with some conditions. In this post, I have leveraged ConcurrentDictionary object (FW 4.0) to cache each channel factory from which proxy is generated in a thread-safe manner to tune WCF service performances one step ahead.