Конструктор десериализации не вызывается

Я пытаюсь сериализовать / десериализовать объект, который содержит Dictionary<Tuid,Section>, Это оба пользовательских типа.

В моем коде у меня есть тип шаблона, который содержит Dictionary<Tuid,Section>, Это класс Template, который я пытаюсь сериализовать / десериализовать.

Чтобы решить проблему, связанную с тем, что эта коллекция представляет собой словарь, я реализовал ISerializable интерфейс на моем классе шаблона....

[Serializable]
public class Template : ISerializable
{
    protected Template(SerializationInfo info, StreamingContext context)
    {
        // Deserialize the sections
        List<Tuid> tuids = (List<Tuid>)info.GetValue("Sections_Keys", typeof(List<Tuid>));
        List<Section> sections = (List<Section>)info.GetValue("Sections_Values", typeof(List<Section>));
        this._sections = new Dictionary<Tuid, Section>();

        for (int i = 0; i < tuids.Count; i++)
        {
            _sections.Add(tuids[i], sections[i]);
        }           
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        List<Tuid> tuids = new List<Tuid>();
        List<Section> sections = new List<Section>();

        foreach (KeyValuePair<Tuid, Section> kvp in _sections)
        {
            tuids.Add(kvp.Key);
            sections.Add(kvp.Value);
        }

        info.AddValue("Sections_Keys", tuids, typeof(List<Tuid>));
        info.AddValue("Sections_Values", sections, typeof(List<Section>));
   }

Стратегия здесь заключается в том, чтобы "распаковать" словарь в два отдельных списка и сохранить их по отдельности в сериализованном потоке. Затем они воссоздаются впоследствии.

Мой класс Раздел также влияет ISerializable...

[Serializable]
public class Section : BaseObject
{

    protected Section(SerializationInfo info, StreamingContext context):base(.....)
    {
        // Code
    }

    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
       // code
    }
}

Проблема в том, что когда я сериализуюсь GetObjectData() вызывается как в моем шаблоне, так и в моем разделе, что заставляет меня поверить, что данные являются сериализуемыми и что они сериализуются.

При десериализации вызывается только конструктор десериализации в Template. Конструктор десериализации для Section никогда не вызывается. Результатом этого является то, что вызов info.GetValue("Section_Values"....) возвращает список, но в нем есть один элемент, и этот элемент является нулевым.

Почему мой конструктор для десериализации раздела никогда не вызывается? Может ли быть так, что некоторые данные внутри раздела не сериализуемы? Если так, как узнать, что именно не может сериализовать?

Обновление: я только что заметил, что BaseObject для раздела помечен [Serializable] но не реализует ISerializable,

Кроме того, мне интересно, насколько суетлив код десериализации - будет ли он нацелен на конструктор, который также создает базовый класс?

Обновить..

Хорошо, я отследил проблему до Сериализации Секции. Код выглядит примерно так...

protected Section(SerializationInfo info, StreamingContext context):base(.....)
{
    // Code
}

public void GetObjectData(SerializationInfo info, StreamingContext context)
{

    //info.AddValue("CustomObject", ClientInfo, typeof(CustomObject));
    //info.AddValue("Description", Description, typeof(string));
}

С обеими закомментированными строками ничего не сериализуется и вызывается конструктор десериализации Section, Если я добавлю в строковое значение все еще хорошо. Тем не менее, да - вы уже догадались - если я добавлю CustomObject в поток сериализации, то конструктор десериализации не вызывается.

Обратите внимание, что...

  • Мой конструктор десериализации для Section это пустой метод - я не пытаюсь что-либо делать с десериализованными данными.
  • Базовый конструктор для Section был заглушен для передачи новых допустимых объектов, и я подтвердил, что это работает нормально.
  • Нет исключений, чтобы сказать мне, что CustomObject не может быть сериализовано.
  • CustomObject сериализуем и его GetObjectData() Метод работает нормально, а его построено нормально при десериализации.

Кажется странным, что это просто добавление этого сериализуемого объекта в поток, который фреймворк просто терпит неудачу в конструкторе десериализатора Section!!

Почему это могло произойти?

2 ответа

Одним из вариантов является реализация

[OnDeserializing]
void OnDeserializing(StreamingContext c)
{
    //create what is required here
}

вTemplate класс, так как serrializer по умолчанию не вызывает конструктор для дочерних объектов - Section учебный класс

Я полагаю, что ваша проблема в том, как работает сериализация (кажется, я вспоминаю сначала ее ширину, а не глубину). Это означает, что он десериализует ваш шаблон, а затем создает в нем пространство для добавления в ваши разделы.

Однако эти разделы еще не десериализованы, они будут десериализованы после завершения десериализации шаблона. Вы должны быть в состоянии проверить это, используя точку останова и позволяя вашему коду работать дальше. Способ исправить это - либо решение oleksii, либо аналогичное использование IDeserializationCallback.

Что такое IDeserializationCallback, когда экземпляр завершает десериализацию (и его членов), он вызывает метод, позволяющий вам выполнить некоторую разводку. Я бы попробовал что-то похожее на это ниже:

[Serializable]
public class Template : ISerializable, IDeserializationCallback
{
    private List<Tuid> tuids;
    private List<Section> sections
    protected Template(SerializationInfo info, StreamingContext context)
    {
        tuids = (List<Tuid>)info.GetValue("Sections_Keys", typeof(List<Tuid>));
        sections = (List<Section>)info.GetValue("Sections_Values", typeof(List<Section>));
        this._sections = new Dictionary<Tuid, Section>();
    }

    public void OnDeserialization(object sender)
    {
        // Section serialization constructor should have been called by this point
        for (int i = 0; i < tuids.Count; i++)
        {
            _sections.Add(tuids[i], sections[i]);
        } 
    }
}
Другие вопросы по тегам