Это распространенная проблема при разборе файла. Обычно вы читаете известную часть дескриптора (которая, к счастью, в данном случае имеет фиксированную длину, но не всегда), и переходите туда. Обычно я использую здесь шаблон стратегии , так как обычно я ожидаю, что система будет в целом гибкой, но прямой коммутатор или фабрика также могут работать.
Другой вопрос: вы контролируете и доверяете нижестоящему коду? Значение: фабрика / реализация стратегии? Если вы это сделаете, то вы можете просто дать им поток и количество байтов, которое, как вы ожидаете, они будут использовать (возможно, установив некоторые отладочные утверждения, чтобы убедиться, что они делают читают точно правильное количество).
Если вы не можете доверять реализации фабрики / стратегии (возможно, вы разрешите пользовательскому коду использовать пользовательские десериализаторы), тогда я создам оболочку поверх потока (пример ) : SubStream
из protobuf-net ), который позволяет использовать только ожидаемое количество байтов (сообщая об EOF впоследствии), и не разрешает операции поиска и т. Д. Вне этого блока. Я бы также проверил во время выполнения (даже в выпусках сборки), что было использовано достаточно данных - но в этом случае я бы, вероятно, просто прочитал за пределами любых непрочитанных данных - то есть, если бы мы ожидали, что нисходящий код будет занимать 20 байтов, но он будет читать только 12 затем пропустите следующие 8 и прочитайте наш следующий дескриптор.
Чтобы расширить это; один дизайн стратегии может иметь что-то вроде:
interface ISerializer {
object Deserialize(Stream source, int bytes);
void Serialize(Stream destination, object value);
}
Вы можете создать словарь (или просто список, если число невелико) таких сериализаторов для ожидаемых маркеров и разрешить ваш сериализатор, а затем вызвать метод Deserialize
. Если вы не узнаете маркер, то (один из):
- пропустить указанное количество байтов
- сгенерировать ошибку
- хранить дополнительные байты в буфере где-нибудь (с учетом обхода неожиданных данных)
В качестве дополнения к вышесказанному - этот подход (стратегия) полезен, если система определяется во время выполнения, либо с помощью отражения, либо с помощью DSL времени выполнения (и т. Д.). Если система является полностью предсказуемой во время компиляции (потому что она не изменяется или потому, что вы используете генерацию кода), тогда прямой switch
подход может быть более подходящим - и вы, вероятно, не не нужно никаких дополнительных интерфейсов, так как вы можете ввести соответствующий код напрямую.