6

テキストを含むストリームがあり、そのストリームの一部のテキストを編集 (一部の値を置換) したいと考えています。

ストリームを壊さずにこれを行う最も効率的な方法は何ですか? のカスタム パイプライン コンポーネントでこれを使用したいと考えていますBizTalk

public IBaseMessage Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
    string msg = "";
    using (VirtualStream virtualStream = new VirtualStream(pInMsg.BodyPart.GetOriginalDataStream()))
    {
        using(StreamReader sr = new StreamReader(VirtualStream))
        {
            msg = sr.ReadToEnd();
        }

        // modify string here
        msg = msg.replace("\r\n","");

        while (msg.Contains(" <"))
           msg = msg.Replace(" <", "<");

        VirtualStream outStream = new VirtualStream();
        StreamWriter sw = new StreamWriter(outStream, Encoding.Default);
        sw.Write(msg);
        sw.Flush();
        outStream.Seek(0, SeekOrigin.Begin);

        pInMsg.BodyPart.Data = outStream;
        pContext.ResourceTracker.AddResource(outStream);
    }

    return pInMsg;
}

これはコードですが、ご覧のとおり、実行するとストリームが中断されますsr.ReadToEnd()

これを行うより良い方法はありますか?

4

3 に答える 3

5

直感的に疑問に思ったように、パイプライン コンポーネントで Stream クラスを使用しているという事実は、それ自体がストリーミング パイプラインコンポーネントにはなりません。

最も適切な方法は、責任を 2 つのコンポーネントに分割することです。

  • 最初に、顧客System.IO.Streamクラスを作成します。これは、元の着信ストリームをラップし、ストリーミング インターフェイスを公開するクラスです。このクラスでは、バイトが呼び出し元のコードによって読み取られるときに、バイトを効果的に処理します。このクラスは BizTalk に依存してはならず、BizTalk 外でこのクラスのサンプル単体テスト プログラムを作成できるはずです。

最初のケースについては、ソース コード サンプルを含むいくつかの記事 のいずれかを参照することをお勧めします。

  • 2 つ目は、パイプライン コンポーネント自体です。このパイプライン コンポーネントの唯一の責任は、受信ストリームをカスタム ストリームのインスタンスに置き換えることです。これは、優れたパイプライン コンポーネントに見られる慣用的なパターンです。特に、Execute メソッドの実行中は、元の受信ストリームを読み取らないでください。読み取りは、メッセージング エージェントが引き継ぐときに自動的に行われます。

次のスニペットは、メソッドの正規のソース コードである必要があります。もちろん、エラー処理用の追加コードは除きます。Execute

IBaseMessage IComponent.Execute(IPipelineContext pContext, IBaseMessage pInMsg)
{
   // assign a new CustomStream to the incoming message

    System.IO.Stream stream = pInMsg.BodyPart.GetOriginalDataStream();
    System.IO.Stream customStream = new CustomStream(stream);

    // return the message for downstream pipeline components (further down in the pipeline)

    pInMsg.BodyPart.Data = customStream;
    pContext.ResourceTracker.AddResource(customStream);

    return pInMsg;
}

見る?前の方法では何も読んでいません。Read処理全体は、カスタムStreamクラスのメソッドの (繰り返される) 呼び出し中に発生する必要があります。

次の質問への回答で書いたように、ストリーミング パイプライン コンポーネントの開発についてNic Bardenが行った一連の投稿をすべてチェックすることを強くお勧めします。

于 2011-01-19T23:33:54.203 に答える
2

シーク不可能な読み取り専用ストリームの単純なケースでは、必要に応じてオンザフライで置換を行うラッパー ストリームをStream.Read(および場合によってはStream.ReadByte) メソッドで作成できます。ただし、これらは生のバイトで機能するため、ストリームのエンコードも考慮する必要がある場合があります。

于 2011-01-07T14:04:35.213 に答える