在我们的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>) ,而不是通过这种工厂模式。

10-08 18:23