将流传递给多个方法,这样做是否可以?

13

我有一个定义如下的接口:

public interface IClientFileImporter
{
    bool CanImport(Stream stream);
    int Import(Stream stream);
}

该想法是将任何文件流通过一系列实现此接口的实现来确定哪个实现应处理该文件。其中一些实现可能会查找特定的标题行,而其他实现则可能会查找特定的字节序列等等...

我的问题是,只要我从未关闭它,把流像这样传递是否可以?如果必要,每种方法都必须负责将流重置为位置0,但除了线程安全性之外还有其他潜在的问题吗?在我看来,这段代码真的很不好,但我不确定有更好的方法来解决它。


我认为这不是一个坏的概念。你不知道实现会从流中需要什么,因此提供整个流是有意义的。为了确保实现不会干扰流,你可以在Stream周围实现某种包装器(从流本身派生),禁止修改底层流或其他所需的任何方法。此外,我不需要实现重置流位置。CanImport/Import的调用者可以执行此操作。结合起来,这确保了没有导入程序可以损害底层流。 - Andre Loker
5个回答

4
为了防止底层流被修改,创建一个派生自Stream的包装流,并仅将安全调用转发到包装流。此外,在使用Import/CanImport方法时不要假设流位置会重置。在调用这些方法之前,调用者应将流重置为有效状态。

在这个只读流包装器中,覆盖Dispose方法以自动倒回流但不关闭它是否可以? - Chris
是的,那肯定可以行得通,这样你就可以在调用CanImport/Import时使用方便的using块。 - Andre Loker

2
这应该不是问题。虽然我可能会稍微重新组织一下:

尽管如此,我可能会稍微重新结构化一下:

public interface IClientFileImporter
{
    int Import(Stream stream);
}

如果导入方法无法完成任务,我建议返回-1。这样可以让你的其他代码更简单。


我同意Chris的观点,很好的回答Chris。我认为这会让它变得更容易。 - Dmitry Savy
是的,像1989年那样返回-1。虽然在C中-1很常见,但在.NET中并不常见,更好的返回值应该是布尔值。 - Fred

2
如果每个函数都按照原样返回流,我认为这没有问题。

为什么方法不应该修改流?我认为从流中读取和写入是你需要传递它的原因。 - cadrell0
如果修改了流,函数之间可能会出现各种依赖关系。这可能没问题,但 OP 提到每次都要倒回流。 - zmbq

0

如果您担心传递流,因为您可能最终运行不可信的外部代码,那么您所能做的最好的方法就是创建一个新的只读流并传递它,以便没有外部代码可以更改文件的内容,直到您确定要让它们这样做。

public class ReadOnlyStream : Stream
{
    private Stream _ownerStream;

    public ReadOnlyStream(Stream baseStream)
    {
        _ownerStream = baseStream;
    }
    
    public override bool CanWrite => false;
    
    public override int Write(byte[] bits, int offset, int count)
    {
        throw new InvalidOperationException();
    }
    
    // Other code omitted
}

0

将同一流传递给多个方法是完全可以的。

要注意不可寻址流 - 有些流无法重置位置。Andre Loker的评论提供了很好的建议,即包装Stream以便CanImport方法不会干扰实际流。

您还可以考虑明确提供流的某些“头”部分给CanImport方法,这样它们就不那么灵活了。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接