即使在类前插入[Serializable]也会出现Serializable错误

本文关键字:Serializable 错误 插入 | 更新日期: 2023-09-27 18:17:47

我创建了一个类

[Serializable]
public class clsCategories
{
    public static List<infoCategories> listCategories = new List<infoCategories>();
    public void serialize()
    {
        BinaryFormatter bf = new BinaryFormatter();
        FileStream fs = new FileStream("categories.dat", FileMode.Create);
        bf.Serialize(fs, listCategories);
        fs.Close();
    }
    [Serializable]
    public class infoCategories
    {
        public PictureBox img { get; set; }
        public Label lbl { get; set; }
    }
}

现在当调用这个方法…

 private void btnDone_Click(object sender, EventArgs e)
 {
     objCategories.serialize();
     this.Hide();
 }

我得到这个错误:

类型的未处理异常"System.Runtime.Serialization。SerializationException'发生在mscorlib.dll

附加信息:键入"System.Windows.Forms"。图片框"System.Windows大会"。形式,版本=2.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089'未标记为可序列化。

我错在哪里?

即使在类前插入[Serializable]也会出现Serializable错误

当序列化infoCategories类型的对象列表时,这些对象的所有属性都被序列化。所以是img性质,碰巧是PictureBox类型。因为PictureBox本身是不可序列化的-你会得到错误。

顺便说一下,同样的情况也会发生在Label lbl上。没有窗口控件可以以这种方式序列化。

你有什么选择?

第一:用[NonSerialized]标记类中所有不可序列化的字段。这使得序列化程序在读写期间跳过该属性。但是,由于这实际上会导致一个空类-在这里这可能不是一个好的选择。

另一种选择是序列化在使用对象时保存和恢复对象所需的非常简单的数据。所以不是序列化Label,而是序列化string,它恰好是这个标签的文本。反序列化之后,您可以从字符串列表中重新创建标签列表。这同样适用于包含在图片框中的图像(可以是base64编码为字符串)。

最后一个选项是序列化代理(当您没有该类的源代码时,是否有可能对对象进行. net二进制序列化?),但这在这里可能是多余的。

在评论和Kuba的回答中说PictureBoxLabel是不可序列化的,这就是错误的原因。用Serializable属性来装饰一个类是不够的,它的所有属性也应该是Serializable

相反,您可以创建一个包含字符串和图像的类,并尝试将其序列化。但不幸的是,Image也不能序列化。

注意:我没有使用Bitmap,因为PicturebBox的图像可能是gif或其他东西。

如何序列化一个包含图像和字符串的类?

对于图像,应该将其序列化为byte[]。所以你可以这样创建一个类:

using System;
using System.Drawing;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
[Serializable]
public partial class MyData
{
    public string Label { get; set; }
    byte[] bytes;
    [NonSerialized]
    Image image;
    public Image Image
    {
        get
        {
            if (image == null && bytes != null)
                image = (Image)((new ImageConverter()).ConvertFrom(bytes));
            return image;
        }
        set
        {
            image = value;
            bytes = (byte[])new ImageConverter().ConvertTo(value, typeof(byte[]));
        }
    }
}

然后要序列化和反序列化它,可以在类中添加SaveLoad方法。

public partial class MyData
{
    public void Save(string file)
    {
        using (Stream stream = File.Open(file, FileMode.Create))
        {
            BinaryFormatter bin = new BinaryFormatter();
            bin.Serialize(stream, this);
        }
    }
    public static MyData Load(string file)
    {
        using (Stream stream = File.Open(file, FileMode.Open))
        {
            BinaryFormatter bin = new BinaryFormatter();
            return (MyData)bin.Deserialize(stream);
        }
    }
}

下面是一个用法示例:

var m1 = new MyData() { Label = label1.Text, Image = pictureBox1.Image };
m1.Save(@"d:'m1.dat");
var m2 = MyData.Load(@"d:'m1.dat");
label2.Text = m2.Label;
pictureBox2.Image = m2.Image;