2017-02-24 71 views
1

我想安全地處理我的WCF客戶端,但我不確定是否在正確的位置實現了IDisposable。爲WCF服務客戶端實現IDisposable - 我正在做對嗎?

我添加的代碼在Reference.vb文件中的服務客戶端時,我加入了WCF服務作爲服務的引用,是爲了實現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子目錄中找到我的斷點。

任何幫助表示讚賞!

回答

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; 
} 

正如你看到的,也有在此界面兩種方法。其中一個將用於調用具有返回類型的服務方法,另一個將用於服務中的無效方法。您也可以將這些方法的非通用版本添加到接口中。

的實現可能是這樣的:

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()但是injectIProxy作爲ServiceProxy,並且現在將它用作WCF客戶端,但是如果它將來改變爲Web API,例如實現並注入WebApiProxy
  • 您可以使用合約接口來調用代理方法。
  • 你可以做任何你想要的代理類像緩存渠道,從數據庫等
+0

這看起來像一個很好的解決方案,我儘管如此,我還是需要一些時間來實施。 C#已經足夠接近了! – cjw

0

你並不需要處理客戶獲取服務端點。事實上,如果你深入研究ClientBase的代碼,你會看到它已經實現了IDisposable,當它被處理時它只是調用Close() - 如果出現錯誤,它會有錯誤處理路徑來中止。

話雖如此,我會用類似下面的模式關閉您的客戶端通道(可能需要轉換爲IChannel上關閉並中止):

try 
{ 
    client.Close(); 
} 
catch 
{ 
    client.Abort(); 
}