Почему protobuf-Net вызывает метод получения свойства во время десериализации, но метод set пока не был вызван - PullRequest
0 голосов
/ 27 сентября 2018

У меня есть свойство, которое зависит от допустимого состояния объекта.Я гарантирую это либо во время создания объекта, либо в функции OnDeserialized.

Теперь я получил магическое исключение во время десериализации protobuf-net, поскольку объект еще не был действителен, поскольку получатель свойства ужевызывается во время десериализации.Ни сеттер не был вызван, ни метод OnDeserialized (OnDeserializing был вызван!)

Я конвертировал из DataContractSerializer, поэтому SkipConstructor должен обеспечить идентичное поведение (я не хочу его удалять).Код выглядит примерно так:

[ProtoContract(SkipConstructor = true, EnumPassthru = true)]
public class MyClass
{
    [OnSerializing]
    [ProtoBeforeSerialization]
    private void OnSerializing(StreamingContext c)
    {
        // first in here
    }

    [OnSerialized]
    [ProtoAfterSerialization]
    private void OnSerialized(StreamingContext c)
    {
        //
    }

    [ProtoMember(1)]
    private AnotherClass[] NetworkValues
    {
        get {   /* Why here after OnSerializing? */ }
        set { }
    }
}

Я не понимаю.Для чего используется геттер во время десериализации?

1 Ответ

0 голосов
/ 27 сентября 2018

Две причины

Во-первых: протокол буфера по существу определяет десериализацию как «слияние» - позволяя объединять данные в существующие объекты и позволяя объединять два потока байтов, чтобы они функционировали как слияние.Таким образом, он предполагает, что он выполняет слияние, по умолчанию , что делает protobuf-net, в случае списков, это

  • получить существующий список, еслиодин;иначе создайте новый список
  • добавьте все новые элементы в этот список (существующие или новые)
  • назначьте список свойству, если оно изменилось

Это поведение можно переопределить, установив для свойства OverwriteList значение true для [ProtoMember], что позволяет всегда обрабатывать свойство как новый список (поэтому: ранее существующие элементы будут потеряны)


Во-вторых, библиотека должна поддерживать очень распространенный шаблон - средства доступа к списку только для чтения.Этот не действительно нужен для массивов, но большая часть кода применима к обоим - но по существу:

private readonly List<AnotherClass> _networkValues = new List<AnotherClass>();
[ProtoMember(1)]
public List<AnotherClass> NetworkValues => _networkValues;

В этом случае механизм only библиотека должна получить список: get.

Примечание: библиотека также хочет избежать ненужных списков в этом сценарии, так что даже если было сеттер, он предпочел бы не создавать новый список.Но опять же - большая часть этого не применяется в случае массивов, поскольку массивы всегда должны быть перераспределены для изменения их размера.

...