将嵌套的 using 语句替换为一个 using 语句
Replace nested using-statement with one using statement
我发现自己在重复这段代码
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 序列化。
我尝试实现自己的 Stream class,将所有方法转换为私有 属性 CryptoStream。但这没有成功。总是在对应的地方坏掉,我一开始就试着读IV。
这是一个非常粗略的示例,说明您正在尝试做什么。有很多地方可以改进,但这是一个工作示例,您可以希望以此为基础。
首先,我们创建一个实现 IDisposable
的 class。这允许我们在 using
语句中使用此 class。 class 将实例化我们需要的其他三个对象,并自行处理它们。
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
}
现在,我们可以像这样使用这个class:
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();
}
}
如果您 运行 这个例子,您可以看到它使用 cryptostream
将 "Test string"
写入文件,然后从该文件读回相同的文本。查看text
的值,仍然是"Test string"
,说明程序成功。
辅助函数怎么样?
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>);
我发现自己在重复这段代码
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 序列化。
我尝试实现自己的 Stream class,将所有方法转换为私有 属性 CryptoStream。但这没有成功。总是在对应的地方坏掉,我一开始就试着读IV。
这是一个非常粗略的示例,说明您正在尝试做什么。有很多地方可以改进,但这是一个工作示例,您可以希望以此为基础。
首先,我们创建一个实现 IDisposable
的 class。这允许我们在 using
语句中使用此 class。 class 将实例化我们需要的其他三个对象,并自行处理它们。
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
}
现在,我们可以像这样使用这个class:
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();
}
}
如果您 运行 这个例子,您可以看到它使用 cryptostream
将 "Test string"
写入文件,然后从该文件读回相同的文本。查看text
的值,仍然是"Test string"
,说明程序成功。
辅助函数怎么样?
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>);