У меня есть библиотека (написанная на С#), для которой мне нужно читать/записывать представления моих объектов на диск (или на любой поток) в определенном двоичном формате (чтобы обеспечить совместимость с реализациями библиотеки C/Java). Формат требует значительного количества бит-упаковки и некоторых DEFLATE'd bytestreams. Тем не менее, я хотел бы, чтобы моя библиотека была как можно более идиоматической .NET, и поэтому хотела бы предоставить API как можно ближе к нормальному процессу двоичной сериализации. Я знаю о возможности реализации интерфейса IFormatter, но поскольку я действительно не могу повторно использовать какую-либо часть встроенного стека сериализации, стоит ли это делать, или это просто приведет к ненужным накладным расходам. Другими словами:
Внедрить IFormatter и co.
ИЛИ
Просто предоставляйте методы "Сериализовать" / "Отсериализировать", которые действуют на поток?
Хороший момент, приведенный ниже, о необходимости семантики сериализации для любого случая, связанного с Remoting. В случае, когда использование объектов MarshalByRef является выполнимым, я уверен, что это не будет проблемой, поэтому оставляя в стороне, есть ли какие-либо выгоды или недостатки в использовании ISerializable/IFormatter в сравнении с пользовательским стеком (или, я понимаю неверно удалены)?
Написание собственного кода сериализации является подверженным ошибкам и требует много времени.
Как мысль - считали ли вы существующие переносные форматы с открытым исходным кодом, например, буферы протокола "? Это формат двоичной сериализации высокой плотности, который лежит в основе большей части передачи данных Google и т.д. Версии доступны на широком спектре языков, включая Java/С++ и т.д. (В основном дистрибутиве Google) и широкий диапазон других.
В частности, для .NET-идиоматического использования protobuf-net выглядит лот как XmlSerializer
или DataContractSerializer
(действительно, он может работать даже с атрибутами xml/wcf, если он включает в себя порядок для каждого элемента) - или может использовать конкретные атрибуты protobuf-net:
[ProtoContract]
class Person {
[ProtoMember(1)]
public string Name {get;set;}
}
Если вы хотите гарантировать переносимость других реализаций, рекомендуется начать "контракт сначала" с файлом ".proto" - в этом случае что-то вроде:
message person {
required string name = 1;
}
Этот .proto файл затем может использоваться для создания любого варианта, специфичного для языка; так что с protobuf-net вы запускаете его через "protogen" (входит в protobuf-net, а также добавляется дополнение VS2008); или для Java/С++ и т.д. вы можете запустить его через "protoc" (включен в Google protobuf). "protogen" в protobuf-net может в настоящее время выпускать С# и VB, но довольно просто добавить другой язык, если вы хотите использовать F # и т.д. - он просто включает в себя запись (или миграцию) xslt.
Существует также другая версия .NET, которая является более прямым портом версии Java; как таковой он меньше идиоматичен .NET. Это dotnet-protobufs.
Я всегда ходил с последним. При повторном использовании схемы сериализации использование большого количества ресурсов мало, если все, что вы делаете, это запись файла в определенную структуру. Единственное место, где я столкнулся с любыми проблемами с использованием настраиваемой структуры сериализации, - это когда вы удаляете, вы должны сделать ваши объекты сериализуемыми.
Это может не помочь вам, поскольку вы должны писать в определенном формате, но protobuf и sqlite - хорошие инструменты для выполнения пользовательской сериализации.
Я бы сделал первое. Это не так много для интерфейса, и поэтому, если вы имитируете структуру так или иначе, добавив ": IFormatter
", а другой код, необходимый для полной совместимости, не займет много времени.