C# 未调用反序列化构造函数

C# 未调用反序列化构造函数,c#,.net,serialization,iserializable,C#,.net,Serialization,Iserializable,我正在尝试序列化/反序列化包含字典的对象。这两种都是自定义类型 在我的代码中,我有一种模板,其中包含字典。我正试图序列化/反序列化的是模板类 为了解决这个集合是字典的问题,我在我的模板类上实现了ISerializable接口 [Serializable] public class Template : ISerializable { protected Template(SerializationInfo info, StreamingContext context) {

我正在尝试序列化/反序列化包含
字典的对象。这两种都是自定义类型

在我的代码中,我有一种模板,其中包含
字典
。我正试图序列化/反序列化的是模板

为了解决这个集合是字典的问题,我在我的模板类上实现了
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>));
   }
问题是,当我序列化
GetObjectData()
时,我的模板和节都被调用,这使我相信数据是可序列化的,并且它正在被序列化

当我反序列化时,只调用模板上的反序列化构造函数。从未调用节的反序列化构造函数。其结果是对
info.GetValue(“Section\u 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));
}
注释掉这两行后,将不序列化任何内容,并在
部分
上调用反序列化构造函数。如果我加入字符串值,一切仍然正常。但是,是的-您猜对了-如果我将
CustomObject
添加到序列化流中,则不会调用反序列化构造函数

请注意

  • 我的
    的反序列化构造函数是一个空白方法-我不尝试对反序列化的数据执行任何操作
  • 节的基本构造函数已经被删除,以便传入新的有效对象,我已经确认这运行正常
  • 不会抛出异常来告诉我无法序列化
    CustomObject
  • CustomObject
    是可序列化的,其
    GetObjectData()
    方法运行良好,其构造在反序列化时运行良好
似乎很奇怪,如果纯粹是将这个可序列化对象添加到流中,那么框架就无法使用
节的反序列化器构造函数


为什么会发生这种情况?

其中一个选项是实施

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

模板
类中,由于默认的Serriaizer不调用子对象的构造函数-

我相信您的问题是因为序列化的工作方式(我似乎记得它是宽度优先,而不是深度优先)。这意味着它将反序列化您的模板,然后在其中创建空间以添加到您的节中

但是,这些部分尚未反序列化,它们将在模板完成反序列化后反序列化。您应该能够通过使用断点并让代码在更远的地方运行来检查这一点。解决这个问题的方法可以是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]);
        } 
    }
}
[可序列化]
公共类模板:ISerializable,IDeserializationCallback
{
私人名单;
私人名单部分
受保护的模板(SerializationInfo、StreamingContext上下文)
{
tuids=(List)info.GetValue(“Sections_Keys”,typeof(List));
sections=(List)info.GetValue(“sections_Values”,typeof(List));
这是。_sections=new Dictionary();
}
公共序列化(对象发送方)
{
//此时应调用节序列化构造函数
for(int i=0;i
Ok,看起来是个好主意-如何将我的子对象提取到我的模板类中?此外,反序列化如何知道列表中有1个对象但其为空,这很奇怪。我不太确定,但我假设您可以重用
模板
的构造函数中的代码。我认为这更适合于在不希望序列化的类中设置值。例如,如果你有一个计算值,你可以从另外两个值中计算出来。你可以用这个方法来计算。我喜欢你序列化字典的方法:)我不知道这是不是一个好方法:)目前它不起作用,所以不会那么好:)你是如何获得要调用的GetObjectData的?我尝试了一段时间,但这个方法从未被调用
[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]);
        } 
    }
}