【问题标题】:Events not working with after Deserialization反序列化后事件不起作用
【发布时间】:2010-09-27 20:13:22
【问题描述】:

问题:

我有一个 Child 类,它使用 DataContractSerialization 并在设置其 Name 属性时引发 Changed 事件。

<DataContract()>
Public Class Child

    Public Event Changed()

    <DataMember()>
    Private _Name As String

    Public Sub New(ByVal NewName As String)
        _Name = NewName
    End Sub

    Public Property Name() As String
        Get
            Return _Name
        End Get
        Set(ByVal value As String)
            _Name = value
            RaiseEvent Changed()
        End Set
    End Property

End Class

它包含在一个 Parent 类中,该类也使用 DataContractSerialization 并处理 Child 的 Changed 事件。

<DataContract()>
Public Class Parent

    <DataMember()>
    Private WithEvents Child As Child

    Private Sub Child_Changed() Handles Child.Changed

        'Handle changed event here...

    End Sub

End Class

Parent 类被序列化和反序列化,所有数据(包括 Child)都按预期保存和重新存储。

但是,在反序列化之后,Changed 事件永远不会引发!

问题:

我知道反序列化过程绕过了类构造函数,但是事件不应该被初始化吗?

我做错了吗?

是否可以序列化/反序列化事件?

是否有比以下更好的解决方法(见下文)?

有没有办法在 Child 而不是 Parent 的 OnDeserialzed 方法中初始化事件(见下文)?

解决方法:

(1) 向 Child 类添加一个构造函数,该构造函数将自身的实例作为参数。

(2) 在Parent类中添加一个OnDeserialized方法,该方法基于Child类的反序列化实例创建一个Child类的New实例。

<OnDeserialized()>
Private Sub OnDeserializedMethod(ByVal Context As StreamingContext)

    Child = New Child(Child)

End Sub

现在 Changed 事件按预期引发。

【问题讨论】:

    标签: .net vb.net events datacontractserializer


    【解决方案1】:

    问题不在于没有触发 Changed 事件;只要将相同的类定义(使用引发事件的 setter)用于反序列化对象(使用不是必需的 DataContract 序列化),就会引发事件。发生的事情是反序列化的对象不再附加处理程序。

    您不能序列化或反序列化事件处理程序;至少,你不应该。因为它们可能指向当前对象引用以外的引用,并且因为反序列化对象是可能是不同运行时中的新引用,所以来自序列化对象的事件处理程序引用在反序列化时是无用的,因为引用将不再指向新运行时堆中的预期对象。

    该解决方案比您的解决方法要容易一些,但基于相同的想法;在将处理程序重新附加到子事件的父项中实现自定义反序列化行为:

    <OnDeserialized()>
    Private Sub OnDeserializedMethod(ByVal Context As StreamingContext)
    
        AddHandler Child.Changed AddressOf Me.Child_Changed
    
    End Sub
    

    这避免了实例化一个新 Child 以销毁另一个 Child 的内存和时间成本,并且应该做同样的伎俩。技术上可以在 Child 上执行此操作,但 Child 需要使用反向引用了解其 Parent。它也有点倒退;一般来说,事件引发者不会“抓取”事件处理程序,而是由包含或了解处理程序和事件的其他对象提供它们。

    【讨论】:

      猜你喜欢
      • 2012-07-11
      • 1970-01-01
      • 2020-10-16
      • 2012-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多