Можно ли передавать поток по нескольким методам?
У меня есть интерфейс, определяемый как:
public interface IClientFileImporter
{
bool CanImport(Stream stream);
int Import(Stream stream);
}
Идея состоит в том, чтобы взять любой поток файлов и запустить его через ряд реализаций этого интерфейса, чтобы определить, какой из них должен обрабатывать файл. Некоторые из реализаций могут искать определенную строку заголовка, в то время как другие могут искать определенную последовательность байтов и т.д.
Мой вопрос в том, нормально ли проходить такой поток, пока я его никогда не закрываю? Каждый метод должен был бы отвечать за сброс потока в позицию 0, если это необходимо, но есть ли другие потенциальные проблемы (кроме безопасности потоков)? Этот код действительно пахнет, ИМО, но я не уверен в лучшем способе сделать это.
Ответы
Ответ 1
Чтобы предотвратить изменение базового потока, создайте поток обертки, который происходит из Stream и пересылает только безопасные вызовы в обернутый поток. Кроме того, не принимайте методы Import/CanImport reset позицию потока. Вызывающий из этого метода должен reset передать поток в действительное состояние, прежде чем передать его в Import/CanImport.
Ответ 2
Если каждая функция возвращает поток только так, как он его получил, я не думаю, что есть проблема с ним.
Ответ 3
Это не должно быть проблемой.
Хотя я бы, вероятно, немного изменил структуру:
public interface IClientFileImporter
{
int Import(Stream stream);
}
Тогда у меня был бы метод импорта return -1, если он не смог. Может сделать ваш другой код немного проще.
Ответ 4
Прекрасно передавать один и тот же поток нескольким методам.
Остерегайтесь потоков, не требующих поиска, - есть потоки, в которых вы не можете reset. У Андре Локера есть хороший совет, чтобы обернуть Stream, поэтому методы CanImport не испортили реальный поток.
Вы также можете явно указать некоторую часть потока заголовка в методы CanImport, а также сделать их менее гибкими.
Ответ 5
Если вы беспокоитесь о передаче потока, потому что вы можете запустить внешний код, который может быть ненадежным, лучше всего сделать новый поток readonly и передать его так, чтобы внешний код не мог меняться содержимое файла, пока вы не уверены, что хотите их оставить.
public class ReadonlyStream : Stream
{
public ReadonlyStream(Stream baseStream)
{
ownerStream = baseStream;
}
private Stream ownerStream;
public override bool CanWrite
{
get { return false; }
}
public override int Write(byte[] bits, int offset, int count)
{
throw new InvalidOperationException();
}
// Other code ommitted
}