2016-09-07 30 views
0

根據MSDN,實現IDisposable接口的最佳方式包括使用SafeHandle類的一個實例。當試圖正確使用依賴注入和IDisposable接口時,我應該注入一個SafeHandle實例嗎? C#

given example他們有以下行;

SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true); 

我一直在閱讀有關依賴注入和TDD和我的理解是,爲了都遵循TDD和正確實現IDisposable接口我會做這樣的事情;

public class SomeDisposableClass : IDisposable 
{ 
    private readonly Stream _stream; 
    private readonly IDisposable _safeHandle; 

    public SomeDisposableClass(Stream stream, IDisposable safeHandle) 
    { 
     _stream = stream; 
     _safeHandle = safeHandle; 
    } 

    private bool disposed = false; 

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

    protected virtual void Dispose(bool disposing) 
    { 
     if (disposed) return; 

     if (disposing) 
     { 
      _safeHandle.Dispose(); 
      _stream.Dispose(); 
     } 

     disposed = true; 
    } 
} 

我正在注入我的safeHandle,而不是在SomeDisposableClass中實例化它。這將允許我傳遞一個模擬並聲明Dispose方法在SomeDisposableClass實例調用其Dispose()方法的情況下被調用。

這是使用TDD和依賴注入時要做的正確事情,還是我把事情做得太過分? (即可以實例化某些類而不是注入它們,還是應該避免像瘟疫一樣的「新」?)

我知道我的示例存在問題(例如,您沒有義務傳入SafeHandle實例,只有一個IDisposable實例)。

+0

爲什麼你認爲你應該注入句柄,而不是在課堂上創建它?這與TDD有什麼關係? – stuartd

+0

我對TDD的理解是,除非我有一個失敗的測試,否則我不能編寫代碼,我應該只寫最少量的代碼來通過測試。如果我堅持這一點,那麼我看不到我如何創建句柄,因爲我不能寫一個測試來斷言句柄被創建。 –

回答

1

您不應該使用DI爲您的班級提供SafeHandleSafeHandle是您班級的內部實施細節,用於實現IDisposable。你的類的用戶不必知道這個內部實現。 DI旨在爲您的課程提供您的課程與之合作的外部實體。不要害怕將new用於僅在班級中使用的對象。

一本非常好的資源是這本書:http://www.growing-object-oriented-software.com/我不能在這裏描述整本書,但這裏有一些想法。他們談論「價值」和「對象」。

值是建模固定量的不可變實例。對象 ...使用可變狀態來模擬他們的行爲隨着時間的推移。

本書中描述的樣式使用DI來連接彼此協作並使用模擬對象來測試這些協作的「對象」網絡。另一方面,在生產和測試代碼中需要時使用new創建「值」,並將其作爲參數和返回值傳遞。

+0

嗨邁克,感謝您的回答(+1),這非常有幫助。如果你可以詳細說明在練習TDD時如何使用「新」(以及爲什麼可以這麼做),或者甚至指向正確的方向,我肯定會將其標記爲正確的答案。我同意用戶不必知道內部實現,但SafeHandle是抽象的,用戶可能希望通過特定的實現,例如基於給定示例中的流類型。 –

+0

一次性類的目的是封裝一些非託管資源 - 一次性類擁有該資源並管理其生命週期,方法是創建一個SafeHandle並在SafeHandle上調用Dispose。在你的例子中,類傳遞了一個Stream,這意味着類的調用者擁有Stream,調用者應該對它的生命週期負責。這就是爲什麼我不認爲你應該將SafeHandle傳遞給一個班級 –