类序列化导致外部库中的stackOverflowException

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了类序列化导致外部库中的stackOverflowException相关的知识,希望对你有一定的参考价值。

我试图序列化/反序列化BindingList到XML文件,但总是得到一个错误:

System.Xml.dll中发生了未处理的“System.StackOverflowException”类型异常

据我所知,它是由于一些无效的引用(get,set,return this)和无限的recurssions引起的。两天浪费没有成功。

数据使用BindingSource和BindingList绑定在一起,也显示在dataGridView中。

我初始化所有可序列化的类:

public Person persons = new Person();

我创建了bindingSources:

BindingSource bsPerson = new BindingSource();

在main函数中,我创建了添加了项的所有BindingLists:

BindingList<Person> persons = new BindingList<Person>()
{
    new Person()
    {
        Surname = "Abc", Phone = "123",
        Address = "Street 1",
        Email = "some@domain.com",
        Car = new BindingList<Car>() { cars[0], cars[1]} }
};

这是我的可序列化类:

[Serializable]
public class Person : BindingList<Person>
{
    public string Surname { get; set; }
    public string Phone { get; set; }
    public string Addres { get; set; }
    public string Email { get; set; }
    public BindingList<Car> Car { get; set; }

    public Person()
    {
        Car = new BindingList<Car>();
    }
}

[Serializable]
public class Car
{
    public string Model { get; set; }
    public int Mileage { get; set; }
    public DateTime ManufactureDate { get; set; }
    public int WheelCount { get; set; }
    public string FuelType { get; set; }
    public int Seats { get; set; }
    public GearBox GearBox { get; set; }
    public Car self { get { return this; } }
}

[Serializable]
public class GearBox
{
    public string Name { get; set; }
    public int CountOfTransfers { get; set; }
    public string Type { get; set; }
    public GearBox self {get {return this;} }
}

[Serializable]
public class ServiceVisits
{
    public DateTime ServiceInDate { get; set; }
    public DateTime ServiceOutDate { get; set; }
    public double Bill { get; set; }
    public string EmployeeName { get; set; }
    public BindingList<ServiceParts> ServiceParts { get; set; }

    public ServiceVisits()
    {
        ServiceParts = new BindingList<ServiceParts>();
    }

    public Company Company { get; set; }
    public Car Car { get; set; }
}

[Serializable]
public class Company
{
    public string Name { get; set; }
    public string Phone { get; set; }
    public int VatNumber { get; set; }
    public string Address { get; set; }
    public Company self { get { return this; } }

}

[Serializable]
public class ServiceParts
{
    public string Name { get; set; }
    public double Price { get; set; }
}

这就是我调用serialize函数的方法:

Serializeri.Serializacija<Person>(persons, path);

这就是我调用deserialize函数的方法:

Serializeri.Deserializacija<Person>(persons, path);

这是包含序列化/反序列化函数的类:

public static class Serializeri
{
    public static void Serializacija<T>(this BindingList<T> list, string       path)
    {
        try
        {
            SaveFileDialog sfd = new SaveFileDialog();
            sfd.Filter = "XML Faili (*.xml) | *.xml";

            if (sfd.ShowDialog() == DialogResult.OK)
            {
                XmlSerializer srz = new XmlSerializer(typeof(BindingList<T>));
                XmlWriter xw = XmlWriter.Create(sfd.FileName);
                srz.Serialize(xw, list);
                xw.Flush();
                xw.Close();
            }
        }
        catch (IOException)
        {
            MessageBox.Show("Nevar saglabāt failu, jo to izmanto cits process!", "Kļūda", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }

    public static void Deserializacija<T>(this BindingList<T> list, string path)
    {
        try
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.Filter = "XML Faili (*.xml) | *.xml";

            if (ofd.ShowDialog() == DialogResult.OK)
            {
                XmlSerializer srz = new XmlSerializer(typeof(BindingList<T>));
                XmlReader xr = XmlReader.Create(ofd.FileName);

                var obj = (BindingList<T>)(srz.Deserialize(xr));

                list.Clear();

                foreach (var element in obj)
                {
                    list.Add(element);
                }

                xr.Close();                    
            }
        }
        catch (IOException)
        {
            MessageBox.Show("Nevar atvērt failu, jo to izmanto cits process!", "Kļūda", MessageBoxButtons.OK, MessageBoxIcon.Error);
        }
    }
}

如何修复它以便序列化工作?我对界面不是很熟悉,如果我能在这个时候避开它们会很好。

调试后我发现有时数据没有正确添加。它显示在dataGridView中,但实际的BindingList为空(count = 0)。

答案

Person没有理由成为自己的集合。无论如何你永远不会把它当作自己的集合,所以如果你不把它当成一个就没有损失。当我从BindingList<Person>中删除基类Person时,序列化不再无限地递归。

public class Person 
{
另一答案

问题是我在Main函数中定义了BindingList<Person>和所有其他列表。基本上我的Serialize / Deserialzie函数访问的是类的实例(与BindingLists同名)而不是真正的列表。

我将BindingList<Person> persons;移动到Main类的开头,它开始工作并保存数据(对功能的修改也很少)。

以上是关于类序列化导致外部库中的stackOverflowException的主要内容,如果未能解决你的问题,请参考以下文章

跨越不同JVM的Java标准库中的SerialVersionUID

外部链接的 C 库中的异常传播

在我的控制器中使用外部类

ASAN - 抑制外部库中的报告(LLVM 13,Windows)

Java中的I/O流的基本知识

搜索栏导致应用程序在我的 ios 库中崩溃