2016-02-04 70 views
1

我正在寫一個相當大的API,並且對我應該如何實現IDisposable感到困惑。在一個簡化的場景中:在API中實現IDisposable

我在我的一個類中有一個Socket(稱爲A),這顯然需要處理,但是該類只有內部構造函數,因此我的用戶只能創建一個實例通過創建更高級別對象的實例(稱爲B),該實例將反過來實例化A並從而獲得新對象A的所有權。

我的直覺暗示了使對象A和B都可以使用當用戶在他們的應用程序中處理我們擁有的對象B時,A被丟棄並且套接字也被正確處置。但是,由於這是一個API,它將允許我的用戶在不處置擁有對象B的情況下處理對象A和套接字,因此可能會導致他們自己遇到一些重大問題。

那麼我該如何繼續?至於我可以看到我唯一的選擇是不好的選擇:

  1. 實現IDisposable直覺將有它,並告訴我的用戶不被文檔中愚蠢的。 (非常差)
  2. 實現IDisposable直覺會有,但以防萬一,添加一些可怕的處置檢查整個應用程序/例外(雖然在我的應用程序配置整個小節的情況將是致命的應用反正)。
  3. 只在對象B中實現IDisposable,而是添加一個內部的Dispose方法來安全地處理A和套接字。 (看似最好的主意)

我不太確定我是否有其他選擇,所以我真的希望有人能爲我提供建議。

謝謝。

+0

你看過「使用」塊的選項嗎?它會通過在內部調用Idisposible來做同樣的事情 – DinoMyte

+2

明顯的方法是向A中添加一個內部Close()方法.B可以在其Dispose()方法中調用它。 –

+1

選項3似乎是最好的 – Viru

回答

2

我的直覺建議,使兩個對象A和B IDisposable接口,這樣 當用戶部署我們在他們的應用程序擁有的對象B,A 設置和插座被正確配置的爲好。 然而,由於這是一個API,它可以讓我的用戶處置 對象及燈座沒有所屬對象B的部署和 因此可能會導致自己的一些重大問題。

使兩者都實現IDisposable可能是最好的主意,並清楚地說明了代碼實例需要清理的事實。指示API的使用者在根/擁有對象(B)上調用Dispose。爲了解決API的消費者問題,也可以在擁有的(A)實例上調用Dispose,您可以執行以下操作。

隱藏它

不要暴露從根的資參考A /所屬對象B或通過再次調用到根和穿過到擁有實例,然後方法提供通有限數量。如果你正在談論實際有限數量的不會改變的方法/屬性,這很好。

接口

裹使用封裝和接口(我在這裏假設插座是一個.NET socket class,但如果周圍的插座類其自己的對象實現那麼你的類是套接字訪問包裝已經和無需創建另一個包裝周圍)。包裝應該實現IDisposable和接口應該只暴露你想讓客戶端有權訪問。我不確定你在哪裏創建套接字的實例,但它們應該由擁有的對象或使用工廠模式創建,以便在創建後儘快建立所有者關係。您可以將類定義保留在內部,並僅向API公開接口。

在我看來,這是實現它的最好方式,如果您需要擴展您的API,將來可以靈活地進行更改。

public class Owner : IDisposable 
{ 
    private SocketWrapper _wrapper; 
    public ISocketWrapper SocketAccess { get { return _wrapper; } } 
    public void Dispose() 
    { 
     if (_wrapper != null) 
      _wrapper.Dispose(); 
    } 
} 

public interface ISocketWrapper 
{ 
    // exposed properties/methods 
} 


internal class SocketWrapper : ISocketWrapper, IDisposable 
{ 
    public void Dispose() 
    { 
     // dispose socket 
    } 
} 
+0

隱藏它可能對我的項目很不樂觀!接口聽起來像是一個很好的路線,實際上,謝謝:) – JamJar00

+1

@ JamJar00 - 很高興幫助!當你有時間時,請不要忘記標記爲答案。如果你還沒有這樣做,也考慮使用接口公開你的Owner對象。在具體類中公開得越少,尤其對那些已經實現了行爲並且不是實體(純態持有)類的類越好。它將導致將來更易維護的代碼,並且在擴展API時不必再創建重大更改。 – Igor

+1

我打算等一等,看看是否有其他答案出現,但自從你問得很好以後;)再次謝謝你! – JamJar00

0

好吧,如果你不想說的API用戶部署你的插座,不僅僅只是將其隱藏(做一些包裝或者一些地方插座是私有的)。

以其他方式處置通常是這樣實現的,所以你可以進行級聯配置如果事情已經佈置你不介意。

public class ComplexResourceHolder : IDisposable { 

private IntPtr buffer; // unmanaged memory buffer 
private SafeHandle resource; // disposable handle to a resource 

public ComplexResourceHolder(){ 
    this.buffer = ... // allocates memory 
    this.resource = ... // allocates the resource 
} 

protected virtual void Dispose(bool disposing){ 
     ReleaseBuffer(buffer); // release unmanaged memory 
    if (disposing){ // release other disposable objects 
     if (resource!= null) resource.Dispose(); 
    } 
} 

~ ComplexResourceHolder(){ 
    Dispose(false); 
} 

public void Dispose(){ 
    Dispose(true); 
    GC.SuppressFinalize(this); 
} 

}

代碼示例是從msdn拍攝,你可以找到更詳細的解釋。

相關問題