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

VB.net-序列化具有事件的类,vb.net,serialization,data-binding,Vb.net,Serialization,Data Binding,叹息。。。 我有一个类,它的属性包含事件。当属性的值发生更改时,将触发该事件。该类的实例是表单上信息的支持者。我需要保存表单中的信息,以便以后调用 这里的想法是将属性作为数据源绑定到表单上的文本框和datagridview。这是当类的值更改时更新textbox或datagridview的事件的驱动程序 所以…当我使用以下代码保存静态变量(test)的文件时,它可以正常工作: Dim test As String = "Hello" ' Persist to file Dim save A

叹息。。。 我有一个类,它的属性包含事件。当属性的值发生更改时,将触发该事件。该类的实例是表单上信息的支持者。我需要保存表单中的信息,以便以后调用

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

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

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.Form”System.Windows.Forms,版本=4.0.0.0,区域性=中性,PublicKeyToken=b77a5c561934e089”标记为可序列化

我真正想做的就是将控件的值保存在表单上,以便以后调用


有什么想法吗?

这里可能的失败模式是您的类有一个已订阅的事件。事件处理程序的目标是作为表单类一部分的方法。是的,这不起作用,表单类不可序列化。您也不希望序列化事件,因为它不太可能正确地反序列化

通过对成员应用
属性,可以抑制类成员的序列化。不幸的是,在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
_
用事件分类
_
私有事件作为新System.ComponentModel.EventHandlerList
作为EventHandler的公共自定义事件Foo
AddHandler(作为EventHandler的ByVal值)
AddHandler(“foo”,值)
EndAddHandler
RemoveHandler(ByVal值作为EventHandler)
Events.RemoveHandler(“foo”,值)
末端移除处理器
RaiseEvent(ByVal发送方作为对象,ByVal e作为System.EventArgs)
CType(Events(“foo”),EventHandler.Invoke(sender,e)
端部提升孔
结束事件
""等等。。
末级
你必须为课堂上的每一个事件都这样做。您可以重复使用事件变量,只需将“foo”更改为“bar”。当然没什么乐趣。请考虑一个专用的类,该类只具有要序列化的属性。

,因为您已经说过,“我真正想要做的是将控件的值保留在表单上以供以后回忆”,一些可能的方法是:

  • 递归地遍历窗体上的所有控件(和子控件),并将相关属性存储在可序列化的数据结构中

  • 将控件绑定到内存中的数据库,并从中序列化数据


  • 错误是什么?事件本身不应该成为问题,因为序列化的是道具。这是与设置道具相关的事件的触发吗?上面的帖子中添加了错误。什么是测试?是表格吗?表单不可序列化(控件也不可序列化…至少不能直接序列化)。Test是我正在序列化的变量。在第一种情况下,它是一个简单的字符串。在第二种情况下,它是一个自定义类,而不是一个表单。错误表明NET认为它是一个表单。如果没有看到一些同学,很难说发生了什么。至少你有一个表单引用的属性。汉斯…哇!感谢您的详细解释和示例!这很有效。汉斯:我有个问题。当对象被反序列化时,它在自定义事件中循环通过AddHandler和RemoveHandler。当它在AddHandler中循环时,抛出一个异常“对象引用未设置为对象的实例”。我没有定制活动的经验。我对此感到很困惑。我确实将事件标记为非序列化:uPrivate事件标记为New System.ComponentModel.EventHandlerList