3

我的主窗体上有一个按钮,它调用一个将一些对象序列化到磁盘的方法。我正在尝试将这些对象添加到 ArrayList,然后使用 BinaryFormatter 和 FileStream 对它们进行序列化。

   public void SerializeGAToDisk(string GenAlgName)
    {
        // Let's make a list that includes all the objects we 
        // need to store a GA instance
        ArrayList GAContents = new ArrayList();
        // Structure and info for a GA
        GAContents.Add(GenAlgInstances[GenAlgName]);  
        // There may be several running GA's
        GAContents.Add(RunningGAs[GenAlgName]);  

        using (FileStream fStream = new FileStream(GenAlgName + ".ga", 
            FileMode.Create, FileAccess.Write, FileShare.None))
        {
            BinaryFormatter binFormat = new BinaryFormatter();
            binFormat.Serialize(fStream, GAContents);
        }
    }

运行上述代码时,出现以下异常:

System.Runtime.Serialization.SerializationException 未处理程序集“GeneticAlgApp,版本=1.0.0.0,文化=中性,PublicKeyToken=null”中的消息=类型“WindowsFormsApplication1.Form1”未标记为可序列化。

所以这意味着在我试图保存的对象中的某个地方必须有对主表单的引用。我能看到的唯一可能的引用是 3 个委托,它们都指向主表单代码中的方法。代表也会被序列化吗?我似乎无法将[NonSerialized]属性应用于它们。

还有什么我可能会丢失的吗?更好的是,是否有一种快速的方法可以找到导致问题的参考?

更新:

好吧,我通过将委托保存到临时变量中然后在序列化之前将它们设置为 null 来使我的代码工作。然后我将它们设置回原来的值。似乎应该有更好的方法来做到这一点。请问有什么意见吗?

回答:

除了在序列化之前将它们设置为 null 之外,我想不出一种方法来阻止我的委托被序列化,但是我认为最好的解决方案是更改我的代码以改用事件。正如 Mark Gravell 在他的回答中所说,事件可以通过使用[field:Nonserialized]属性标记从序列化中省略。问题解决了。实际上没有人建议这个,但我想马克的回答是最接近的。

4

3 回答 3

2

这几乎总是意味着您已经从表单订阅了一个事件。是的,委托字段在使用时默认是序列化的BinaryFormatter,也就是说事件是序列化的。检查您的事件:您通常应该标记支持委托[NonSerialized]。对于类似字段的事件,请使用[field:NonSerialized]. 例如:

[field:NonSerialized]
public event EventHandler Foo;

或者:

[NonSerialized]
private EventHandler foo;

public event EventHandler {
    add { foo += value; }
    remove { foo -= value; }
}
于 2012-09-10T08:52:27.187 回答
0

要查找所有引用,在 Visual Studio 中,右键单击该类(我猜这里是主窗体),然后选择 Find All References (Ctrl + K,R)
也让您序列化您需要具有 [Serializable] 属性的东西.
而且我认为您不能序列化代表。

于 2012-09-10T08:45:47.920 回答
0

您的对象可能不支持序列化。如果是您的自定义对象,请使用 [Serializable] 属性标记它们。您还可以阅读本文以了解如何实现您的自定义序列化过程。

于 2012-09-10T08:42:11.153 回答