Vb.net 为WCF服务客户端实现IDisposable-我这样做对吗?
我想安全地处置我的WCF客户端,但我不确定是否在正确的位置实现了IDisposable 我在Reference.vb文件中添加了代码以在服务客户端中实现IDisposable,该文件是在我将WCF服务添加为服务引用时创建的:Vb.net 为WCF服务客户端实现IDisposable-我这样做对吗?,vb.net,wcf,Vb.net,Wcf,我想安全地处置我的WCF客户端,但我不确定是否在正确的位置实现了IDisposable 我在Reference.vb文件中添加了代码以在服务客户端中实现IDisposable,该文件是在我将WCF服务添加为服务引用时创建的: Partial Public Class Service1Client Inherits System.ServiceModel.ClientBase(Of DataConversionService.IService1) Implements DataConversion
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
部分公共类服务1客户端
继承System.ServiceModel.ClientBase(属于DataConversionService.IService1)
实现DataConversionService.IService1,IDisposable
公共分新()
我的基地,新的
端接头
'正在跳过具有多个参数的构造函数。。。
Public Sub Dispose()实现IDisposable.Dispose
尝试
如果状态CommunicationState.Faulted,则
关闭()
如果结束
最后
如果状态为通讯状态。则关闭
中止
如果结束
结束尝试
端接头
我把这个放在正确的位置了吗?调试时,我无法在Dispose子目录中找到断点
感谢您的帮助 你很接近。首先,您不应该更改该
Reference.vb
文件,因为当服务定义更新时,它将被覆盖,并且更改该文件不是一个好的做法
你能做的是使用。代理将用于调用服务中的方法和管理连接状态等。我将用C#编写,因为我不懂VB,但你会明白的。我将尽可能地简化这个过程
代理类的接口可能如下所示:
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;
}
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());
公共接口IProxy
{
///
///执行服务调用方法
///
///服务接口
///服务方法返回类型
///服务方式
///返回服务方法返回的内容
TResult Execute(Func调用),其中TBusiness:class;
///
///执行对void服务方法的调用
///
///服务接口
///服务方式
无效执行(操作调用),其中TBusiness:class;
}
如您所见,此接口中有两种方法。其中一个将用于调用具有返回类型的服务方法,另一个将用于服务中的void方法。您也可以将这些方法的非泛型版本放到接口中
实现可能如下所示:
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;
}
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());
公共类ServiceProxy:IProxy
{
受保护的void ExecuteCall(操作代码),其中TContract:class
{
var contractChannel=默认值(t合同);
尝试
{
//创建服务客户端实例并调用该方法
contractChannel=Activator.CreateInstance();
代码(合同频道);
((ICommunicationObject)contractChannel.Close();
}
捕获(错误异常)
{
((ICommunicationObject)contractChannel.Abort();
}
捕获(通信异常)
{
((ICommunicationObject)contractChannel.Abort();
}
捕获(超时异常)
{
((ICommunicationObject)contractChannel.Abort();
}
}
public TResult Execute(Func调用),其中TContract:class
{
返回ExecuteCall(call);
}
public void Execute(操作调用),其中TContract:class
{
执行调用(call);
}
}
然后,您可以这样使用它:
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;
}
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());
var proxy=new ServiceProxy();
Execute(a=>a.MethodInTheService());
这种方法的优点以及如何使其完美:
- 您可能不希望将代理创建为
,而将new ServiceProxy()
创建为IProxy
,并暂时将其用作WCF客户端,但如果它将来更改为Web API,例如,实现并注入ServiceProxy
,则可以WebApiProxy
- 您可以使用契约接口来调用代理方法
- 您可以在代理类中执行任何您想要的操作,比如缓存通道、从数据库获取服务端点等
- 您不需要处理客户端。事实上,如果您深入研究的代码,您将看到它是如何实现IDisposable的,当它被释放时,它只调用Close()——如果出现问题,它有错误处理路径可以中止
说到这里,我将使用类似于下面的模式来关闭您的客户端通道(您可能需要在关闭和中止时强制转换到IChannel):
这看起来是一个很好的解决方案,不过我需要一些时间来处理实现。C#够近了!