Если в существующем коде состояния сеанса используется BinaryFormatter
, вы можете обмануть, заставив protobuf-net выступать в качестве внутреннего прокси для BinaryFormatter
, реализовав ISerializable
только для вашего корневого объекта :
[ProtoContract]
class SessionObject : ISerializable {
public SessionObject() { }
protected SessionObject(SerializationInfo info, StreamingContext context) {
Serializer.Merge(info, this);
}
void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
Serializer.Serialize(info, this);
}
[ProtoMember(1)]
public string Foo { get; set; }
...
}
Примечания:
- для этого нужен только корневой объект;любые инкапсулированные объекты будут обрабатываться автоматически с помощью protobuf-net
- , который по-прежнему будет содержать метаданные типа da small для самого внешнего объекта, но не так много
- , которые вам понадобятсясоответственно декорировать элементы (и инкапсулированные типы) (лучше всего это делать явно для каждого члена; существует неявный режим «разберись сам», но это будет хрупко, если вы добавите новых членов)
- это будет сломать существующее состояние ;изменение механизма сериализации является принципиально критическим изменением
Если вы хотите исключить метаданные типа из объекта root , вам придется реализовать свой собственный поставщик состояний (я думаю, что тамявляется примером для MSDN);
- преимущество: меньший вывод
- преимущество: не нужно реализовывать
ISerializable
для корневого объекта - недостаток: вам нужноподдержите своего собственного провайдера состояний; p
(все остальные пункты, поднятые выше, все еще применяются)
Обратите внимание также, что эффективность protobuf-net здесь будет немного зависеть от того, какие данныеэто то, что вы хранитеОн должен быть меньше, но если у вас много огромных строк, он не будет на много меньше, так как protobuf по-прежнему использует UTF-8 для строк.
Если вы у есть много строк, вы можете дополнительно рассмотреть возможность использования gzip - я написал провайдера состояний для моего последнего работодателя, который пробовал gzip, и хранил то, что было меньше (оригинальное или gzip) - очевидно, с несколькими проверками, например:
- не используйте gzip, если оно меньше, чем [какое-либо значение]
- закоротите сжатие gzip на ранней стадии, если gzip превысит исходное
Вышесказанное можно использовать в сочетании с protobuf-net довольно удачно - и если вы пишете провайдеру состояния в любом случае , вы можете отказаться от ISerializable
и т. Д. Для максимальной производительности.
И последний вариант, , если вы действительно хотите, чтобы означало, что мне нужно добавить свойство "режима сжатия" к [ProtoContract(..., CompressionMode = ...)]
;который:
- будет применяться только для использования
ISerializable
(по техническим причинам нет смысла менять основной макет, но этот сценарий будет приемлемым) - автоматически применяет gzip во время сериализации / десериализации вышеупомянутого [возможно, с теми же проверками, о которых я упоминал выше)
- означало бы, что вам не нужно добавлять свой собственный поставщик состояний
Однако,это то, что я действительно хотел бы подать заявку на "v2" (я довольно жестоко отношусь к исправлению ошибок только в v1, так что я могу держать все в порядке).
Дайте мне знать, если это будетинтерес.