即使在类之前插入[Serializable]之后也会出现可序列化错误

时间:2016-11-14 18:38:13

标签: c# winforms serialization

我创建了一个类

[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.PictureBox”   程序集'System.Windows.Forms,Version = 2.0.0.0,Culture = neutral,   PublicKeyToken = b77a5c561934e089'未标记为可序列化。

我错在哪里?

2 个答案:

答案 0 :(得分:4)

序列化infoCategories类型的对象列表时,会序列化这些对象的所有属性。 img属性也是如此,它恰好是PictureBox类型。由于PictureBox本身不可序列化 - 您会收到错误。

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

你有什么选择?

首先:使用[NonSerialized]标记班级中所有不可序列化的字段。这使得序列化程序在读取和写入期间跳过该属性。但是,因为这基本上会导致一个空类 - 这可能不是一个好选择。

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

最后一个选项是序列化代理(Is it possible to do .NET binary serialization of an object when you don't have the source code of the class?),但这在某种程度上可能是一种过度杀伤。

答案 1 :(得分:2)

在评论和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;