未调用反序列化构造函数



我正在尝试序列化/反序列化一个包含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>));
   }
这里的策略是将字典"解包"为两个单独的列表,并将它们单独存储在序列化流中。然后重新创建它们。

My Section类也实现了ISerializable

[Serializable]
public class Section : BaseObject
{
    protected Section(SerializationInfo info, StreamingContext context):base(.....)
    {
        // Code
    }
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
       // code
    }
}

问题是,当我序列化GetObjectData()在我的模板我的Section上调用时,这让我相信数据是可序列化的,并且它正在被序列化。

反序列化时,只调用Template上的反序列化构造函数。永远不会调用Section的反序列化构造函数。这样做的结果是,调用info.GetValue("Section_Values"....) 确实返回一个列表,但其中有一个项目,该项目是空的。

为什么我反序列化Section的构造函数永远不会被调用?可能是部分中的某些数据不可序列化吗?如果是,如何找出它不能序列化的具体内容?

更新:我刚刚发现的一件事是,BaseObject的部分被标记为[Serializable],但不实现ISerializable

另外,我想知道反序列化代码是多么的繁琐-它会针对构造函数也构造基类吗?

更新…

好的,我找到了问题出在Section的序列化上。代码看起来像这样…

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的反序列化构造函数!!

为什么会发生这种情况?

其中一个选项是实现

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

,因为默认序列化器不调用子对象的构造函数- Section

我相信你的问题是由于序列化的工作方式(我似乎记得它的宽度第一,而不是深度第一)。这意味着它反序列化你的模板,然后在里面创建空间来添加你的章节。

这些节还没有被反序列化,它们将在模板完成反序列化后被反序列化。您应该能够通过使用断点并让代码继续运行一点来检查这一点。解决这个问题的方法要么是oleksii的解决方案,要么类似于使用idesseriizationcallback。

当实例(和它的成员)完成反序列化时,它将调用一个方法来允许您进行一些连接。我将尝试下面这样做:

[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]);
        } 
    }
}

相关内容

  • 没有找到相关文章

最新更新