I'm trying to convert an existing .NET Remoting application to WCF. Both server and client share common interface and all objects are server-activated objects.
In WCF world, this would be similar to creating per-call service and using ChannelFactory<T>
to create a proxy. I'm struggling a bit with how to properly create ChannelFactory<T>
for an ASP.NET client.
For performance reasons, I want to cache ChannelFactory<T>
objects and just create channel every time I call the service. In .NET remoting days, there used to be RemotingConfiguration.GetRegisteredWellknownClientTypes()
method to get a collection of client objects that I could then cache. It appears, in WCF world there is no such thing, although I was able to get a collection of endpoints from config file.
Now here is what I think will work. I can create something like this:
public static ProxyHelper
{
static Dictionary<Type, object> lookup = new Dictionary<string, object>();
static public T GetChannel<T>()
{
Type type = typeof(T);
ChannelFactory<T> factory;
if (!lookup.ContainsKey(type))
{
factory = new ChannelFactory<T>();
lookup.Add(type, factory);
}
else
{
factory = (ChannelFactory<T>)lookup[type];
}
T proxy = factory.CreateChannel();
((IClientChannel)proxy).Open();
return proxy;
}
}
I think the above code will work, but I'm a bit worried about multiple threads trying to add new ChannelFactory<T>
objects if it's not in the lookup. Since I'm using .NET 4.0, I was thinking about using ConcurrentDictionary
and use GetOrAdd()
method or use TryGetValue()
method first to check if ChannelFactory<T>
exists and it does not exist, then use GetOrAdd()
method. Not sure about performance though of ConcurrentDictionary.TryGetValue()
and ConcurrentDictionary.GetOrAdd()
method.
Another minor question is whether I need to call ChannelFactory.Close()
method on channel factory objects after ASP.NET application ends or can I just let .NET framework dispose the channel factory objects on its own. The proxy channel will always be closed after calling service method by using ((IChannel)proxy).Close()
method.
Best Answer
Here's a helper class that I use to handle channel factories:
Then I define a service invoker:
and an implementation:
Now every time you need to call a WCF service you could use this:
This assumes that you've defined a client endpoint for the
IMyServiceContract
service contract in the config file: