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 类的事实并不像您直观地想知道的那样使其成为Streaming 管道组件本身。

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

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

对于第一种情况,我建议您浏览几篇 带有源代码示例的文章中的一篇。

  • 其次,管道组件本身,其唯一职责是将传入流替换为您的自定义流的实例。这是一种惯用模式,您可以在良好的管道组件中找到它。特别是,在执行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 回答
0

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

不关心冲洗部分,我在想自己如何以最好的方式做到这一点,因为我需要编写一个通用的字符串替换流。

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

于 2013-07-19T14:47:08.993 回答