VB.net - 序列化具有事件的类

时间:2013-10-02 19:32:48

标签: vb.net serialization data-binding

...叹息 我有一个具有事件属性的类。当属性值发生更改时会触发该事件。该类的实例是表单信息的支持者。我需要保存表单中的信息以供日后调用。

这里的想法是将属性作为数据源绑定到表单上的文本框和datagridview。这是事件的驱动程序,当类的值发生更改时,更新文本框或datagridview。

所以...当我使用下面的代码来保存静态变量(测试)的文件时,它可以正常工作:

Dim test As String = "Hello"
    ' Persist to file
Dim save As New SaveFileDialog
If save.ShowDialog = Windows.Forms.DialogResult.OK Then
    Dim stream As FileStream = File.Create(save.FileName)
    Dim formatter As New BinaryFormatter()
    formatter.Serialize(stream, test)
    stream.Close()
End If

如果我使用支持数据的类的实例尝试它,它会因为类有事件而抛出错误:

Dim test As new ClassWithEvents()
    ' Persist to file
Dim save As New SaveFileDialog
If save.ShowDialog = Windows.Forms.DialogResult.OK Then
    Dim stream As FileStream = File.Create(save.FileName)
    Dim formatter As New BinaryFormatter()
    formatter.Serialize(stream, test)
    stream.Close()
End If

错误:

  

在程序集'System.Windows.Forms中输入'System.Windows.Forms.Form',Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089'未标记为可序列化。

我真正想做的就是将控件的值保留在表单上以供日后调用。

有什么想法吗?

2 个答案:

答案 0 :(得分:1)

这里可能的失败模式是你的班级有一个订阅的事件。事件处理程序的目标是一个Form类的一部分。是的,这不起作用,Form类不可序列化。你也不希望序列化事件,它不太可能正确地反序列化。

通过在成员上应用<NonSerialized>属性来禁止对成员进行序列化。不幸的是,在VB.NET中很难做到,它不适用于使用Event关键字声明的成员。 VB.NET事件相当特殊。解决方法是使用自定义事件,使用私有支持字段,您可以阻止序列化。看起来像这样:

<Serializable()> _
Class ClassWithEvents
    <NonSerialized()> _
    Private Events As New System.ComponentModel.EventHandlerList

    Public Custom Event Foo As EventHandler
        AddHandler(ByVal value As EventHandler)
            Events.AddHandler("foo", value)
        End AddHandler

        RemoveHandler(ByVal value As EventHandler)
            Events.RemoveHandler("foo", value)
        End RemoveHandler

        RaiseEvent(ByVal sender As Object, ByVal e As System.EventArgs)
            CType(Events("foo"), EventHandler).Invoke(sender, e)
        End RaiseEvent
    End Event

    '' etc..
End Class

你必须为班上的每个活动做到这一点。您可以重复使用Events变量,只需将“foo”更改为“bar”即可。当然不是很有趣。请考虑一个只有您想要序列化的属性的专用类作为替代。

答案 1 :(得分:0)

既然你已经说过“我真正想做的就是将控件的值保留在表单上以供日后调用”,一些可能的方法是:

  1. 以递归方式循环遍历表单上的所有控件(和子控件),并将相关属性存储在可序列化的数据结构中。

  2. 将您的控件绑定到内存数据库,并从中序列化您的数据。