HXLDCont无法序列化,因为缺少一个无参数的构造函数

答案概括:

#####

问题:HXLDCont无法序列化,因为缺少一个无参数的构造函数

原因:反序列化时候必须用一个无参数的构造函数进行反序列化,这是要将类的方法给反序列化出来。因为方法不参与序列化,只能在反序列化属性字段之后通过无参数的构造函数重新生成。

解决办法:如果一个对象没有构造函数就不能序列化反序列化,可以将其反编译然后硬性加一个没用的构造函数即可进行序列化反序列化

####

说明:

现在想来,如果是由我来实现一个类型通用的序列化器,真是必须要有一个无参构造函数。为什么?

先回答我一个问题:

序列化器的序列化的是类的哪些成员? 答:字段,属性,一切的方法都不会参与序列化过程

有了这点就够了,我们知道类型的方法一旦经过编译就不能修改,方法的实现已经写在程序集里面了,所以我们没有必要把它序列化出来,这样只会多此一举,而且还浪费空间。我们可以将序列化的过程看成是先创建一个对象,然后再对对象里面的成员进行赋值(这就是为什么要被xml序列化的成员是publilc,public说明成员可以在类的外部进行赋值,对象一旦被创建就会为它分配空间)。

由于编译器是很笨的,他不会自动识别构造函数的参数,所以这里就需要一个无参数的构造函数来新建一个类,这样就能保证类型总能成功新建对象。(试想一下Perso对象是null你能对它的成员赋值吗?)

我认为反序列化的部分过程应该是这样

//==============================================================

引用:https://www.cnblogs.com/fornet/archive/2013/09/27/3343588.html

//==============================================================

//==============================================================

为什么.Net要求序列化的类必须有一个无参数的构造函数

刚才用xml序列化器,序列化一个类,结果报错说序列化的类必须带有一个无参的构造函数,好奇怪啊。为什么要有这么苛刻的条件,而且xml序列化还要求序列化的成员是public。

我以前一直觉得序列化器是一个很神奇的东西,因为它可以把一个对象保存在一个文件中,然后可以通过反序列化将文本文件还原成对象,觉得用起来很方便,而忘了思考它是怎样实现的。

先上一个例子:

[Serializable]

    public class Persons:List<Person>

    {       

      public void SaveData(string path)

        {

            using (FileStream fs = new FileStream(path, FileMode.Create))

            {

                XmlSerializer formatter = new XmlSerializer(typeof(Persons));

                formatter.Serialize(fs, this);

            }

        }

      public static Persons LoadDataFromFile(string path)

        {

            Persons sc;

            using (FileStream fs = new FileStream(path, FileMode.Open))

            {

                XmlSerializer formatter = new XmlSerializer(typeof(Persons));

                sc = (Persons)formatter.Deserialize(fs);

            }

            return sc;

        }

     

    }

  Person类:

[Serializable]

public class Person

{

    public string Name { get; set; }

    public int Age { get; set; }

    public Person(string name)

    {

        Name = name;

        Age = 0;

    }

    public Person()

    {

        Name = string.Empty;

        Age = 0;

    }

}

  

现在想来,如果是由我来实现一个类型通用的序列化器,真是必须要有一个无参构造函数。为什么?

先回答我一个问题:

序列化器的序列化的是类的哪些成员? 答:字段,属性,一切的方法都不会参与序列化过程

有了这点就够了,我们知道类型的方法一旦经过编译就不能修改,方法的实现已经写在程序集里面了,所以我们没有必要把它序列化出来,这样只会多此一举,而且还浪费空间。我们可以将序列化的过程看成是先创建一个对象,然后再对对象里面的成员进行赋值(这就是为什么要被xml序列化的成员是publilc,public说明成员可以在类的外部进行赋值,对象一旦被创建就会为它分配空间)。

由于编译器是很笨的,他不会自动识别构造函数的参数,所以这里就需要一个无参数的构造函数来新建一个类,这样就能保证类型总能成功新建对象。(试想一下Perso对象是null你能对它的成员赋值吗?)

我认为反序列化的部分过程应该是这样

复制代码

Person p=new Person();//这里必须遵守序列化的对象都带有一个无参构造函数,保证对象非null
//此处省略若干处理代码
p.Name="John";
p.Age=10;

复制代码

调用无参构造函数生成一个Person类,然后通过一系列的对xml的处理解析得知Person类中有两个字段属性 然后对这两个字段属性赋值

至此一个Person就被成功反序列化出来,以上纯属个人观点,如果你觉得不对请指出。

//==============================================================

//==============================================================

//==============================================================

//#################################################################下面才是正解:

[未找到反序列化“XXX”类型对象的构造函数。]的解决办法

转载:https://blog.csdn.net/mirmuo/article/details/7102506

出现[未找到反序列化“XXX”类型对象的构造函数。]错误一般是由于要反序列化的类或者它的父类(如:继承了Dictionary类)实现了ISerializable接口而没有序列化构造函数,这时候只要把序列化构造函数加上去就可以反序列化了。需要注意的是,一个类或者它的父类实现ISerializable接口就表示启用了自定义序列化,需要按照自定义序列化的规则编写序列化构造函数和GetObjectData函数,像下面的两个例子。


    [Serializable]
    class Test : ISerializable //实现了ISerializable接口
    {
        public Test()
        {
        }
 
        //实现了ISerializable接口的类必须包含有序列化构造函数,否则会出错。
        protected Test(SerializationInfo info, StreamingContext context)
        {
            Value = info.GetBoolean("Test_Value");
        }
 
        #region ISerializable 成员
 
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("Test_Value", Value);
        }
 
        #endregion
 
        public bool Value { get; set; }
    }

    [Serializable]
    class Test : Dictionary<string, string> //父类实现了ISerializable接口(Dictionary实现了ISerializable接口)
    {
        public Test()
        {
        }
 
        //父类实现了ISerializable接口的,子类也必须有序列化构造函数,否则反序列化时会出错。(记得using System.Runtime.Serialization;)
        protected Test(SerializationInfo info, StreamingContext context): base(info, context)
        {
            Value = info.GetBoolean("Test_Value");
        }

 
        public override void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            base.GetObjectData(info, context);
            info.AddValue("Test_Value", Value);
        }
 
        public bool Value { get; set; }
    }

//#################################################################

发布了42 篇原创文章 · 获赞 6 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/u014090257/article/details/89187655