如何在BizTalk管道组件中有效地修改流中的文本?

时间:2011-01-07 13:17:07

标签: c# inputstream biztalk custom-pipeline-component

我有一个包含文本的流,现在我想在该流中编辑一些文本(替换一些值)。

最有效的方法是什么,所以不打破流? 我想在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()时,我正在打破流。

有没有更好的方法来做到这一点?

3 个答案:

答案 0 :(得分:4)

您在管道组件中使用Stream类这一事实并没有像您直观地想到的那样使它成为 Streaming管道组件本身

最合适的方法是将责任分为两个部分:

  • 首先,您创建一个客户System.IO.Stream类 - 这是一个包装原始传入流并公开流接口的类。在这个类中,您将通过调用代码有效地处理字节,因为它们被读取。这个类应该不依赖于BizTalk,你应该能够在BizTalk之外为这个类创建一个示例单元测试程序。

对于第一种情况,我建议您浏览several articles with source code samples之一。

  • 其次,管道组件本身,其唯一的责任是用自定义流的实例替换传入流。这是一个惯用的模式,您可以在良好的管道组件中找到它。特别是,在执行Execute method期间,您不应该阅读原始传入流。当Messaging Agent接管时,读数将自动发生 - 自动

以下代码段应该是 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方法的(重复)调用期间进行。

正如我在回复the following question时写的那样,我强烈建议您查看Nic Barden关于开发流媒体管道组件的所有帖子。

答案 1 :(得分:2)

对于不可查找的只读流的简单情况,您可以创建一个包装器流,根据需要在Stream.Read(可能还有Stream.ReadByte)中进行实时替换。方法。但是,它们使用原始字节,因此您可能还必须考虑流编码。

答案 2 :(得分:0)

我认为保持已完成和处理缓冲区的方式是,当您将新内容写入流中时,将其保留在待处理缓冲区中,直到您知道无需更换任何内容。 在替换或决定之后,没有什么可以替换的,将数据从挂起缓冲区移动到完成缓冲区。 read方法应该只从done缓冲区读取,write应该只写入处理缓冲区并且flush将所有挂起的内容移动到完成。

对于冲洗部分不感兴趣,我正在考虑如何以最佳方式执行此操作,因为我需要编写通用字符串替换器流。

[编辑]抱歉,回复了一个2岁的帖子... [/ edit]