2014-06-12 64 views
6

如果我有一個CryptoStream,我想傳遞給用戶,幼稚的做法是CryptoStream是否可以返回並且仍然可以正確處理所有內容?

public Stream GetDecryptedFileStream(string inputFile, byte[] key, byte[] iv) 
{ 
    var fsCrypt = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read); 
    var rmCrypto = new RijndaelManaged(); 
    var transform = rmCrypto.CreateDecryptor(key, iv); 
    var cs = new CryptoStream(fsCrypt, transform, CryptoStreamMode.Read); 

    return cs; 
} 

我知道,當我處置CryptoStream底層FileStreamwill also be disposed。我遇到的問題是:我如何處理rmCryptotransformRijndaelManagedICryptoTransform是一次性類,但處置流不會處理這兩個對象。

處理這種情況的正確方法是什麼?

+1

按照你的方法,你''從返回GetDecryptedFileStream'之後,因爲它們在你的方法的局部變量rmCrypto'和'transform'應配置。 –

+1

@YuvalItzchakov走出範圍並不意味着被處置。在最後一次發佈'cs'的引用之前,GC不會完成這兩個對象。 –

+0

哦,我沒有看到你的CryptoStream接受它們作爲參數。 –

回答

5

我會考慮創建自己的包裝流的類,然後您可以管理這些處理。沿着這些線的東西(抱歉 - 不知道轉換對象的類型離開我的頭頂)。

public CryptoStreamWrapper : Stream, IDisposable 
{ 
    public CryptoStreamWrapper(CryptoStream stream, RijndaelManaged rmCrypto, IDisposable transform) 
    { 
     this.transform = transform; 
     this.rmCrypto = rmCrypto; 
     this.stream = stream; 
    } 

    public void Dispose() 
    { 
     this.transform.Dispose(); 
     this.rmCrypto.Dispose(); 
     this.stream.Dispose(); 
    } 
} 
+3

其實,這與我在問「問我的鴨子」後提出問題後提出的解決方案非常相似。你可以派生'CryptoStream'。我會發表一個答案。 –

+0

@ScottChamberlain:我喜歡你使用橡皮鴨的事實! – Ian

+0

偉大的解決方案,即將發佈確切的東西 –

5

伊恩打我的基本概念(go upvote him),但CryptoStream的本身是不密封的,因此是微不足道的做一個派生類包裝了需要處理的事情。

/// <summary> 
/// Creates a class that creates a <see cref="CryptoStream"/> and wraps the disposing action of all the associated objects 
/// </summary> 
class ReturnableCryptoStream : CryptoStream 
{ 
    private readonly ICryptoTransform _transform; 
    private readonly IDisposable _algorithm; 

    public ReturnableCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode) 
     : this(stream, transform, mode, null) 
    { 
    } 

    public ReturnableCryptoStream(Stream stream, ICryptoTransform transform, CryptoStreamMode mode, IDisposable algorithm) 
     : base(stream, transform, mode) 
    { 
     _transform = transform; 
     _algorithm = algorithm; 
    } 

    protected override void Dispose(bool disposing) 
    { 
     base.Dispose(disposing); 
     if (disposing) 
     { 
      if (_transform != null) 
       _transform.Dispose(); 

      if (_algorithm != null) 
       _algorithm.Dispose(); 
     } 
    } 
} 

一樣使用

public Stream GetDecryptedFileStream(string inputFile, byte[] key, byte[] iv) 
{ 
    var fsCrypt = new FileStream(inputFile, FileMode.Open, FileAccess.Read, FileShare.Read); 
    var rmCrypto = new RijndaelManaged(); 
    var transform = rmCrypto.CreateDecryptor(key, iv); 
    var cs = new ReturnableCryptoStream(fsCrypt, transform, CryptoStreamMode.Read, rmCrypto); 

    return cs; 
} 
+0

欣賞你的答案中的信用票據:) – Ian

+0

考慮一下,這實際上也是更乾淨,因爲你不需要實現所有其他成員 - 比如Length,ReadByte()等。 – Ian

+0

我在想它可能會在base.Dispose()之後執行transform.Dispose()會更加正確,否則就會丟棄某些基類,以至於基類仍然有引用,並且可能會選擇在其處理過程中進行調用。我不確定你的算法字段是什麼(?)如果它是創建ICryptoTransform的原始對象,那麼只要創建ICryptoTransform就可以將其丟棄,因此您不需要在稍後處理它以供處理。 – redcalx

相關問題