2014-06-12 6 views
6

अगर मैं एक 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। जिस मुद्दे में मैं चल रहा हूं वह है कि मैं rmCrypto और transform के साथ क्या करूँ? RijndaelManaged और ICryptoTransform डिस्पोजेबल कक्षाएं हैं, लेकिन धारा का निपटान उन दो वस्तुओं का निपटान नहीं करता है।

इस स्थिति को संभालने का सही तरीका क्या है?

+1

प्रयुक्त, 'rmCrypto' और' transform' के बाद आप 'GetDecryptedFileStream' से लौटने के रूप में वे अपने विधि में स्थानीय चर रहे हैं निपटारा किया जाना चाहिए। –

+1

@YuvalItzchakov दायरे से बाहर जाने का मतलब निपटान नहीं किया जा रहा है। जीसी उन दो वस्तुओं को अंतिम रूप नहीं देगा जब तक कि 'सीएस' के अंतिम संदर्भ को जारी नहीं किया जाता है। –

+0

ओह, मैं आपकी 'क्रिप्टोस्ट्रीम' को पैरामीटर के रूप में स्वीकार करने में विफल रहा। –

उत्तर

5

मैं अपनी खुद की कक्षा बनाने पर विचार करता हूं जो स्ट्रीम को लपेटता है और फिर आप इनका निपटान प्रबंधित कर सकते हैं। इन पंक्तियों के साथ Somethings (माफ करना - मेरे सिर के ऊपर ट्रांसफॉर्म ऑब्जेक्ट के प्रकार को नहीं पता)।

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

असल में, यह "मेरे बतख से पूछने" के बाद प्रश्न पूछने के बाद आया समाधान के समान ही है। आप 'क्रिप्टोस्ट्रीम' प्राप्त कर सकते हैं। मैं एक उत्तर पोस्ट करूंगा। –

+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

इसके बारे में सोचकर, यह वास्तव में भी क्लीनर है, क्योंकि आपको अन्य सभी सदस्यों को लागू करने की आवश्यकता नहीं है - जैसे लंबाई, रीडबेट() इत्यादि – Ian

+0

मुझे लगता है कि यह हो सकता है परिवर्तन करने के लिए और अधिक सही हो। आधार के बाद() का उपयोग करें।(), अन्यथा, क्योंकि आप किसी अन्य तरीके से निपट रहे हैं कि बेस क्लास में अभी भी एक संदर्भ है और इसकी निपटान प्रक्रिया के दौरान कॉल करना चुन सकता है। मुझे यकीन नहीं है कि आपका एल्गोरिदम फ़ील्ड क्या है (?) यदि मूल ऑब्जेक्टथैट ने आईसीआरपीटी ट्रान्सफॉर्म बनाया है, तो आईसीआरपीटी ट्रान्सफॉर्म बनने के तुरंत बाद इसका निपटारा किया जा सकता है, इसलिए आपको बाद में निपटान के लिए इसे रेफरी रखने की आवश्यकता नहीं है । – redcalx

संबंधित मुद्दे

 संबंधित मुद्दे