In our SharePoint/ASP.NET environment we have a series of data retriever classes that all derive from a common interface. I was assigned the task of creating a data retriever that could communicate remotely with other SharePoint farms using WCF. The way I have it implemented at the moment is a singleton ChannelFactory<T>
is created in a static constructor and then reused by each instance of the remote data retriever to create an individual proxy instance. I figured that this would work well because then the ChannelFactory
only gets instantiated once in an app domain and its creation is guaranteed to be thread-safe. My code looks something like this:
public class RemoteDataRetriever : IDataRetriever
{
protected static readonly ChannelFactory<IRemoteDataProvider>
RequestChannelFactory;
protected IRemoteDataProvider _channel;
static RemoteDataRetriever()
{
WSHttpBinding binding = new WSHttpBinding(
SecurityMode.TransportWithMessageCredential, true);
binding.Security.Transport.ClientCredentialType =
HttpClientCredentialType.None;
binding.Security.Message.ClientCredentialType =
MessageCredentialType.Windows;
RequestChannelFactory =
new ChannelFactory<IRemoteDataProvider>(binding);
}
public RemoteDataRetriever(string endpointAddress)
{
_channel = RemoteDataRetriever.RequestChannelFactory.
CreateChannel(new EndpointAddress(endpointAddress));
}
}
My question is, is this a good design? I figured that once the ChannelFactory
is created I don't need to worry about thread-safety because I'm merely using it to call CreateChannel()
but am I mistaken? Is it changing state or otherwise doing something funky behind the scenes that could cause threading issues? Additionally, do I need to put some code in somewhere (static finalizer?) that manually disposes of the ChannelFactory
or can I assume that whenever IIS gets rebooted it'll do all the cleanup work for me?
Related: ChannelFactory Reuse Strategies
From a "is this singleton design good" well, your implementation of the Singleton is fine. It's thread-safe, and the ChannelFactory<T>
is thread-safe as well.
You also don't have to worry about resource cleanup. Assuming that the ChannelFactory<T>
follows Microsoft's guidelines for implementing IDisposable, then you won't have a problem with a leak of some kind. When an application domain is torn down, a garbage collection will be created, and everything will be cleaned up at that point. The finalizer on ChannelFactory<T>
will do the cleanup one would normally do in the call to Dispose.
However, from a "should I be caching the ChannelFactory<T>
" point of view, it's hard to say, because you don't indicate what version of .NET you are on. However, the article you point to indicates that if you are using .NET 3.0 SP1 or above, you really don't need to do this, you can create your proxies (assuming they derive from ClientBase<T>
) where you need it in the client code, and not through a factory pattern like this.