Vb.net 为WCF服务客户端实现IDisposable-我这样做对吗?

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

我想安全地处置我的WCF客户端,但我不确定是否在正确的位置实现了IDisposable

我在Reference.vb文件中添加了代码以在服务客户端中实现IDisposable,该文件是在我将WCF服务添加为服务引用时创建的:

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
    创建为
    ServiceProxy
    ,并暂时将其用作WCF客户端,但如果它将来更改为Web API,例如,实现并注入
    WebApiProxy
    ,则可以
  • 您可以使用契约接口来调用代理方法
  • 您可以在代理类中执行任何您想要的操作,比如缓存通道、从数据库获取服务端点等

    • 您不需要处理客户端。事实上,如果您深入研究的代码,您将看到它是如何实现IDisposable的,当它被释放时,它只调用Close()——如果出现问题,它有错误处理路径可以中止

      说到这里,我将使用类似于下面的模式来关闭您的客户端通道(您可能需要在关闭和中止时强制转换到IChannel):


      这看起来是一个很好的解决方案,不过我需要一些时间来处理实现。C#够近了!