2016-12-16 106 views
0

我與實現IDisposable第三方對象的工作。爲了使單元測試「能夠」,我構建了一個包裝器。我知道該對象實現IDisposable我的包裝需要實現IDisposable以及。實施和使用IDisposable的

public interface IWrapper : IDisposable 
{ 
    void Complete(); 
} 

public class Wrapper : IWrapper 
{ 
    private readonly ThirdPartyLib lib; 

    public Wrapper() 
    { 
     lib = new ThirdPartyLib(); 
    } 

    public void Complete() 
    { 
     lib.Comlete(); 
    } 

    public void Dispose() 
    { 
     lib.Dispose(); 
    } 
} 

public class Processor : IProcessor 
{ 
    private readonly IWrapper wrapper; 
    public Processor(IWrapper wrapper) 
    { 
     this.wrapper = wrapper; 
    } 

    public void Process() 
    { 
     // do some work 
     using (wrapper) { 
      // do more work 
     } 
    } 
} 

假設處理器在某些類,它是用它和工藝注入()被執行

  • 什麼happends爲包裝,如果我們呼叫處理()再一次? - ThirdPartyLib()不會拋出一個異常,因爲它只被創建一次(在包裝器的構造函數中),現在它已經被處置了
  • 只要有引用它就不會被拋棄嗎?
  • 如果包裝也許可以建立這樣一種方式,新的()可以在構造函數,但在一個單獨的方法不執行ThirdPartyLib的「ing」的,說開始() - 像這樣:
public class Wrapper : IWrapper 
    { 
     private ThirdPartyLib lib; 

     public void Begin() 
     { 
      lib = new ThirdPartyLib(); 
     } 

     public void Complete() 
     { 
      lib.Comlete(); 
     } 

     public void Dispose() 
     { 
      lib.Dispose(); 
     } 
    } 

然後使用它:

using (wrapper.Begin()) { 
+1

我覺得我們沒有這個大圖。爲什麼'Processor'只處理一個被注入到構造函數中的'Wrapper'?通常我會希望你'Processor'有一個方法調用,比如'Process(IWrapper wrapper)',允許你處理這個包裝器,但是我會再次進入陣營,這將是調用者必須致電'處置'在'IWrapper'上,因爲它實際上擁有它。如果情況並非如此,那麼我可能會在'IProcessor'上實現'IDisposable',並且在處理時只處理'IWrapper'。 –

+0

僅在IP處理器上實現IDisposable時,處理IP處理器時(在當前設計中),而不是在使用語句的「}」命中時處理包裝器?這是因爲(父)IP處理器持有對IWrapper的引用 - 即使我們告訴它將被放置在「}」 – BobSwanson

+0

這就是爲什麼用DI初始化的對象應該假設它們擁有注入的object_。大多數時候,他們是由其他對象使用的單身人士,或者至少是別的東西正在控制生命。依賴於DI的對象只應該使用該對象,並假定該對象創建的任何內容都將負責在稍後對其進行覈對。 DI就像_「嘿,我只想要一個對象,別人可以爲我創建和刪除它」_ – MickyD

回答

2

你說的沒錯予以關注。撥打Process()兩次可能會導致異常。根本不打電話Process()會使對象不存在。

有你應該做的,而不是沒有簡單的規則。有多種選擇,可以使用哪些選項取決於代碼中不在您的問題中的其他部分。

如果Processor引用了外部擁有的Wrapper,那麼它應該不會處理該包裝。

如果Processor在施工時取得Wrapper的所有權,則應該在處置時處理該包裝。這意味着Processor應該實現IDisposable爲好。

如果可以修改Processor以根據需要創建新的Wrapper,則可以在完成Process()時處理該包裝。

或者,如您所暗示的,如果Wrapper可以根據需要修改爲創建ThirdPartyLib,那也可以。但要小心:撥打wrapper.Begin(); wrapper.Begin();會留下一個ThirdPartyLib未處理和未處理。您需要更多地重構您的API以防止此問題發生,並且實際上,這意味着將您的Wrapper變成ThirdPartyLibFactory

+0

你能解釋一下如何調用:wrapper.Begin(); wrapper.Begin();會留下一個不存在? – BobSwanson

+0

@BobSwanson'wrapper.Begin()'創建第三方庫,我們將其稱爲A.然後再次調用它,現在創建了第二個第三方庫,我們稱它爲B.現在,您的私有變量'lib'指向B,沒有任何東西指向A了。當你調用'wrapper.End()'時,它會調用放置B的lib.Dispose(),但A仍然存在,因爲你失去了對它的唯一引用,所以不能再進行處理。 – Quantic

1

我覺得Processor不應處置IWrapper,因爲它不是實例化它的人,它不知道是否可以設置,如果它被注入到其他對象。在這種情況下,Processor不應與包裝使用using

處置IWrapper的代碼應該放在首先實例化它的類中,因爲那是知道它的生命週期的代碼。