我想安全地处理我的WCF客户端,但我不确定我是否在正确的位置实现IDisposable。
我添加了代码以在我将WCF服务添加为服务引用时创建的Reference.vb文件中的服务客户端中实现IDisposable:
Partial Public Class Service1Client
Inherits System.ServiceModel.ClientBase(Of DataConversionService.IService1)
Implements DataConversionService.IService1, IDisposable
Public Sub New()
MyBase.New
End Sub
'skipping constructors with multiple parameters...
Public Sub Dispose() Implements IDisposable.Dispose
Try
If State <> CommunicationState.Faulted Then
Close()
End If
Finally
If State <> CommunicationState.Closed Then
Abort()
End If
End Try
End Sub
我是否在正确的位置添加了这个?调试时,我无法在Dispose子中命中断点。
感谢任何帮助!
答案 0 :(得分:3)
你很亲密。首先,您不应该更改Reference.vb
文件,因为当服务定义更新并且更改该文件不是一个好习惯时,它将被覆盖。
你可以做的是使用Proxy Pattern。代理将用于调用服务中的方法并管理连接状态等。我将用C#编写,因为我不了解VB但你会得到这个想法。我将尽可能简化这一点。
Proxy类的接口可能如下所示:
public interface IProxy
{
/// <summary>
/// Execute call to service method
/// </summary>
/// <typeparam name="TBusiness">Service interface</typeparam>
/// <typeparam name="TResult">Service method return type</typeparam>
/// <param name="call">Service method</param>
/// <returns>Returns what service method returns</returns>
TResult Execute<TBusiness, TResult>(Func<TBusiness, TResult> call) where TBusiness : class;
/// <summary>
/// Execute call to void service method
/// </summary>
/// <typeparam name="TBusiness">Service Interface</typeparam>
/// <param name="call">Service method</param>
void Execute<TBusiness>(Action<TBusiness> call) where TBusiness : class;
}
如您所见,此界面中有两种方法。其中一个将用于调用具有返回类型的服务方法,另一个将用于服务中的void方法。您也可以将这些方法的非泛型版本添加到界面中。
实施可能是这样的:
public class ServiceProxy : IProxy
{
protected void ExecuteCall<TContract>(Action<TContract> code) where TContract : class
{
var contractChannel = default(TContract);
try
{
//Create an instance of service client and call the method
contractChannel = Activator.CreateInstance<TContract>();
code(contractChannel);
((ICommunicationObject)contractChannel).Close();
}
catch (FaultException)
{
((ICommunicationObject)contractChannel).Abort();
}
catch (CommunicationException)
{
((ICommunicationObject)contractChannel).Abort();
}
catch (TimeoutException)
{
((ICommunicationObject)contractChannel).Abort();
}
}
public TResult Execute<TContract, TResult>(Func<TContract, TResult> call) where TContract : class
{
return ExecuteCall(call);
}
public void Execute<TContract>(Action<TContract> call) where TContract : class
{
ExecuteCall(call);
}
}
然后,您可以像这样使用它:
var proxy = new ServiceProxy();
proxy.Execute<Service1Client>(a => a.MethodInTheService());
这种方法的优点是什么,以及如何使其完美:
new ServiceProxy()
,而inject IProxy
创建为ServiceProxy
,现在将其用作WCF客户端,但如果它更改为Web API,则未来,例如,实施和注入WebApiProxy
然后。答案 1 :(得分:0)
您不需要处置客户端。实际上,如果你深入研究ClientBase的代码,你会看到它是如何实现IDisposable的,当它被处理掉它只调用Close() - 如果出现问题,它会有错误处理路径中止
说完这个之后,我会使用类似下面的模式关闭你的客户端频道(你可能需要在关闭和中止时转换为IChannel):
try
{
client.Close();
}
catch
{
client.Abort();
}