代码之家  ›  专栏  ›  技术社区  ›  Christian

用一个using语句替换嵌套的using语句

  •  0
  • Christian  · 技术社区  · 8 年前

    我发现自己在重复这个密码

    using (var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read)
    {
      using (var aes = AesCryptoServiceProvider() { Key = ... }
      {
    
        // Read the IV at the beginning of the filestream
    
        using (var cryptoStream = new CryptoStream(fileStream, aes.CreateDecryptor(), CryptoStreamMode.Read)
        {
    
          // Actual code only using cryptoStream
    
        }
      }
    }
    

    和

    using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write)
    {
      using (var aes = AesCryptoServiceProvider() { Key = ... }
      {
    
        // Write the IV at the beginning of the filestream
    
        using (var cryptoStream = new CryptoStream(fileStream, aes.CreateDecryptor(), CryptoStreamMode.Write)
        {
    
          // Actual code only using cryptoStream
    
        }
      }
    }
    

    我扪心自问,如果可以用这样的东西来代替这个

    using (var cryptoStream = new MyDecryptionStream(path))
    {
      // Actual code
    }
    

    实际代码可能非常不同。它可以是一个必须保存的图像或XML序列化。

    我尝试实现自己的流类,该类将所有方法强制转换为私有属性cryptostream。但这没有成功。它总是在对位处断开,我一开始试着读第四章。

    2 回复  |  直到 8 年前
        1
  •  1
  •   N.D.C.    8 年前

    这里有一个 非常粗糙 你想做什么的例子。有很多地方可以进行改进,但它是一个你可以指望的工作样本。

    首先,我们创建一个实现 IDisposable . 这允许我们在 using 声明。这个类将实例化我们需要的其他三个对象,并处理它们的处理,全部由它自己完成。

    class MyCryptoStream : IDisposable
    {
        private FileStream fileStream = null;
        private AesCryptoServiceProvider aes = null;
        public CryptoStream cryptoStream = null;
    
        public enum Mode
        {
            Write,
            Read
        }
    
        public MyCryptoStream(string filepath, Mode mode, byte[] key, byte[] iv = null)
        {
            if(mode == Mode.Write)
            {
                fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Write);
                fileStream.Write(iv, 0, 16);
                aes = new AesCryptoServiceProvider() { Key = key, IV = iv };
    
                cryptoStream = new CryptoStream(fileStream, aes.CreateEncryptor(), CryptoStreamMode.Write);
            }
            else
            {
                iv = new byte[16];
                fileStream = new FileStream(filepath, FileMode.Open, FileAccess.Read);
                fileStream.Read(iv, 0, 16);
                aes = new AesCryptoServiceProvider() { Key = key, IV = iv };
    
                cryptoStream = new CryptoStream(fileStream, aes.CreateDecryptor(), CryptoStreamMode.Read);
            }
        }
    
        #region IDisposable Support
        private bool disposedValue = false; // To detect redundant calls
    
        protected virtual void Dispose(bool disposing)
        {
            if (!disposedValue)
            {
                if (disposing)
                {
                    if (cryptoStream != null)
                    {
                        cryptoStream.Dispose();
                    }
                    if (aes != null)
                    {
                        aes.Dispose();
                    }
                    if (fileStream != null)
                    {
                        fileStream.Dispose();
                    }
                }
    
                // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
                // TODO: set large fields to null.
    
                disposedValue = true;
            }
        }
    
        // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
        // ~UsingReduction() {
        //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        //   Dispose(false);
        // }
    
        // This code added to correctly implement the disposable pattern.
        public void Dispose()
        {
            // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
            Dispose(true);
            // TODO: uncomment the following line if the finalizer is overridden above.
            // GC.SuppressFinalize(this);
        }
        #endregion
    
    }
    

    现在,我们可以这样使用这个类:

            string path = "..\\..\\test.txt";
            byte[] key = null;
            byte[] iv = null;
            using (AesCryptoServiceProvider myAes = new AesCryptoServiceProvider())
            {
                key = myAes.Key;
                iv = myAes.IV;
            }
            using (MyCryptoStream ur = new MyCryptoStream(path, MyCryptoStream.Mode.Write, key, iv))
            {
                using (StreamWriter sw = new StreamWriter(ur.cryptoStream))
                {
                    sw.Write("Test string");
                }
            }
            string text = string.Empty;
            using (MyCryptoStream ur = new MyCryptoStream(path, MyCryptoStream.Mode.Read, key))
            {
                using (StreamReader sr = new StreamReader(ur.cryptoStream))
                {
                    text = sr.ReadToEnd();
                }
            }
    

    如果运行这个示例,您可以看到它的写入。 "Test string" 使用 cryptostream ,然后从该文件中读取相同的文本。检查的值 text 我们可以看到它仍然是 “测试字符串” ,表明程序是成功的。

        2
  •  1
  •   cwharris    8 年前

    助手函数呢?

    public static TResult ReadFileUsingCrypto<TResult>(string path, KeyThing key, Func<CryptoStream, TResult> use)
    {
        using (var fileStream = new FileStream(path, FileMode.Open, FileAccesa.Read))
        using (var aes = new AesCryptoServiceProvider(){...}))
        using (var cryptoStream = new CryptoStream(fileStream, aes.CreateDecryptor(), CryptoStreamMode.Read))
        {
            return use(cryptoStream);
        }
    }
    

    然后

    var result = ReadFileUsingCrypto(“myFile”, key, crypto => <use crypto here and return result>);
    
    推荐文章