2013-12-11 40 views
5

流我試圖通過流作爲參數的最佳方式,但我不知道哪條路是「最好的」,所以想聽聽你的意見/建議到我的代碼示例什麼是繞過

我個人更喜歡選項三,但我更新的地方在其他任何地方都是這樣做的。

選項1是好的小溪流(和已知大小溪流)

選項2_1和2_2將永遠離開了「左撇子」在誰擁有了處置/關閉的責任疑問。

public interface ISomeStreamHandler 
{ 
    // Option 1 
    void HandleStream(byte[] streamBytes); 

    // Option 2 
    void HandleStream(Stream stream); 

    // Option 3 
    void HandleStream(Func<Stream> openStream); 
} 


public interface IStreamProducer 
{ 
    Stream GetStream(); 
} 



public class SomeTestClass 
{ 
    private readonly ISomeStreamHandler _streamHandler; 
    private readonly IStreamProducer _streamProducer; 

    public SomeTestClass(ISomeStreamHandler streamHandler, IStreamProducer streamProducer) 
    { 
     _streamHandler = streamHandler; 
     _streamProducer = streamProducer; 
    } 

    public void DoOption1() 
    { 
     var buffer = new byte[16 * 1024]; 
     using (var input = _streamProducer.GetStream()) 
     { 
      using (var ms = new MemoryStream()) 
      { 
       int read; 
       while ((read = input.Read(buffer, 0, buffer.Length)) > 0) 
       { 
        ms.Write(buffer, 0, read); 
       } 
       _streamHandler.HandleStream(ms.ToArray()); 
      } 
     } 
    } 

    public void DoOption2_1() 
    { 
     _streamHandler.HandleStream(_streamProducer.GetStream()); 
    } 

    public void DoOption2_2() 
    { 
     using (var stream = _streamProducer.GetStream()) 
     { 
      _streamHandler.HandleStream(stream);  
     } 
    } 


    public void DoOption3() 
    { 
     _streamHandler.HandleStream(_streamProducer.GetStream); 
    } 
} 

回答

2

選項2_2是處理可支配資源的標準方式。

您的SomeTestClass實例詢問生產商的流 - 然後SomeTestClass擁有一個流並負責清理。

選項3和2_1依靠不同的對象來清理SomeTestClass所擁有的資源 - 可能無法滿足此期望。

選項1是jut複製流的內容到另一個流 - 我沒有看到這樣做的任何好處。

+0

選項3只是使用「MemoryStream」作爲能夠將流轉換爲字節數組的手段。 - 所以這不是將流內容解析到另一個流的問題。 –

+0

所以要清楚;如果你在哪裏要求impliment「void HandleStream(Stream stream);」你會認爲你的實現沒有責任關閉/處置流? –

+0

@JakobDyrby - 然而,選項3正在讀取'Stream',寫入'MemoryStream',並轉換爲'byte []'。爲什麼不直接從'Stream'讀取並使用緩衝區呢? – dcastro

0

傳遞一個IStream走一走,那裏的一次流起源實施IDisposable。 處理流的責任在於創建它的對象。

+0

所以一個FileInfo對象,有責任在「fi.OpenRead()之後關閉一個流」但事實並非如此呢? –

+0

查看@ dcastro的評論,「根據經驗,關鍵字是所有權,誰擁有IDisposable實例,負責關閉它。」 –

0

您可能沒有意識到這一點,但您正試圖實施管道設計模式。作爲一個起點,考慮考慮看看:

至於您的實現,我建議你去與選項#2:

public interface IStreamHandler 
{ 
    void Process(Stream stream); 
} 

至於對象生存期,這是我的信念,即:

  • 實施應該如何處理呼叫Dispose
  • 如果IStreamHandler沒有呼叫Dispose(n嗷嗷你可以鏈中處理程序的每一天,就像你在Unix的管道會)

第三方解決方案

建立一個管道解決方案可以很有趣,但它也是值得注意的是,也有現有產品市場:

其他注意事項

有建議與您的設計問題選項2

void Process(Stream stream); 

Unix Pipes您可以鏈接多個應用程序一起通過一個程序的輸出並將其作爲另一個程序的輸入。如果要使用選項2構建類似的解決方案,那麼如果使用多個處理程序並且您的數據Stream僅向前(即stream.CanSeek=False),則會遇到問題。

+0

謝謝!我會閱讀這種設計模式。但現在;請你詳細說明你認爲誰有責任關閉處置。我應該如選項2_1還是選項2_2中所示使用界面? –

+0

我會去:DoOption2_2。更重要的是:**(1)**與您的實現一致,並且**(2)**確保在異常拋出異常的情況下釋放所有資源。 – Pressacco

相關問題