如何实现将参数传递给使用 Action<Stream,Stream> 的 StreamedPipeline

How to implement passing of parameter to a StreamedPipeline that uses Action<Stream,Stream>

我在 MSDN 杂志 (https://msdn.microsoft.com/en-us/magazine/cc163290.aspx) 上阅读了一篇关于 .Net StreamedPipeline 实现的精彩文章。

不过我有一个挑战。

在实现中,他们调用了 CompressEncrypt 方法:

using (FileStream input = File.OpenRead("inputData.bin"))
using (FileStream output = File.OpenWrite("outputData.bin"))
using (StreamPipeline pipeline = new StreamPipeline(Compress, Encrypt))
{
    pipeline.Run(input, output);
}

这些方法是预定义的除了 Stream 参数之外没有任何参数

static void Compress(Stream input, Stream output){
    using (GZipStream compressor = new GZipStream(
           output, CompressionMode.Compress, true))
        CopyStream(input, compressor);
}

static void Encrypt(Stream input, Stream output) {
    RijndaelManaged rijndael = new RijndaelManaged();
    ... // setup crypto keys
    using (ICryptoTransform transform = rijndael.CreateEncryptor())
    using (CryptoStream encryptor = new CryptoStream(
            output, transform, CryptoStreamMode.Write))
        CopyStream(input, encryptor);
}

我真正苦苦挣扎的是如何让其他的、额外的、非流的参数被发送到管道。例如,如果是加密,我想发送密钥并将其包含在管道调用中。 如何使用附加参数实现相同的功能?

你可以试试这个:

    byte[] key = // ... your key
    byte[] iv = // ... your initialization vector

    using (FileStream input = File.OpenRead("inputData.bin"))
    using (FileStream output = File.OpenWrite("outputData.bin"))
    using (StreamPipeline pipeline = new StreamPipeline(
        Compress, 
        (i, o) => Encrypt(i, o, key, iv)
    ))
    {
        pipeline.Run(input, output);
    }

static void Compress(Stream input, Stream output){
    using (GZipStream compressor = new GZipStream(
           output, CompressionMode.Compress, true
    ))
        CopyStream(input, compressor);
}

static void Encrypt(Stream input, Stream output, byte[] key, byte[] iv) {
    RijndaelManaged rijndael = new RijndaelManaged();
    using (ICryptoTransform transform = rijndael.CreateEncryptor(key, iv))
    using (CryptoStream encryptor = new CryptoStream(
            output, transform, CryptoStreamMode.Write
    ))
        CopyStream(input, encryptor);
}

您需要使用函数式编程技术,partial application。本质上,您可以创建另一个匿名函数来捕获您的参数并将它们应用于您的实际函数。

var additionalCompressionArgument = 123;
using (FileStream input = File.OpenRead("inputData.bin"))
using (FileStream output = File.OpenWrite("outputData.bin"))
using (StreamPipeline pipeline = new StreamPipeline(
   (input, output) => Compress(input, output, additionalCompressionArgument), 
    Encrypt))
{
    pipeline.Run(input, output);
}

static void Compress(Stream input, Stream output, int additionalCompressionParameter){
    using (GZipStream compressor = new GZipStream(
           output, CompressionMode.Compress, true))
        CopyStream(input, compressor);
}