在我们的SharePoint/ASP.NET环境中,我们有一系列数据检索器类,它们都从一个公共(public)接口(interface)派生。我被分配了创建一个数据检索器的任务,该数据检索器可以使用WCF与其他SharePoint场进行远程通信。我目前实现的方式是在静态构造函数中创建一个单例ChannelFactory<T>
,然后由远程数据检索器的每个实例重用以创建一个单独的代理实例。我认为这样做会很好,因为ChannelFactory
仅在应用程序域中实例化一次,其创建为guaranteed to be thread-safe。我的代码看起来像这样:
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));
}
}
我的问题是,这是一个好的设计吗?我认为一旦创建了
ChannelFactory
,我就不必担心线程安全性,因为我只是用它来调用CreateChannel()
,但我误会了吗?它是在改变状态还是在幕后做一些时髦的事情而可能导致线程问题?另外,我是否需要将一些代码放在手动处置ChannelFactory
的某个地方(静态终结器?),或者可以假设每次重新启动IIS都会为我完成所有清理工作?相关:ChannelFactory Reuse Strategies
最佳答案
从“这个单例设计良好”来看,您对Singleton的实现很好。它是线程安全的,ChannelFactory<T>
也是线程安全的。
您也不必担心资源清理。假设ChannelFactory<T>
跟在Microsoft's guidelines for implementing IDisposable之后,那么您不会遇到任何类型的泄漏问题。当应用程序域被拆除时,将创建垃圾回收,并在那时清理所有内容。 ChannelFactory<T>
的终结器将执行通常在对Dispose的调用中进行的清理。
但是,从“我应该缓存ChannelFactory<T>
”的角度来看,很难说,因为您没有指出所使用的.NET版本。但是,您指向的文章指出,如果您使用的是.NET 3.0 SP1或更高版本,则确实不需要这样做,您可以在客户端代码中需要的位置创建代理(假设它们源自ClientBase<T>
) ,而不是通过这种工厂模式。