类级别,而不是实例,处理自定义事件?

时间:2013-01-03 22:49:44

标签: .net vb.net delegates event-handling com-interop

主窗体是否有某种方法可以监听ClassB的自定义事件的任何引发而不引用引发该事件的ClassB的特定实例?

生成事件的ClassB实例当前在表单知道的ClassA实例中匿名实例化。

(最终更新:我直接调用MainForm方法无效的原因在于我接受的答案to this question。)

更新我怀疑它比我想象的要复杂得多。以下引用解释了为什么我对MainForm.DataReady()的调用不起作用 - 以一种令人抓狂的模糊方式。

  

.NET事件的神奇之处在于,当您通过A的实例订阅B实例中的事件时,A会被发送到B的appdomain中。如果A不是MarshalByRef,则发送A的值副本。现在你有两个独立的A实例,这就是你遇到意外行为的原因。

Cross AppDomain MarshallByRef vs value copy discussion

UPDATE2:

使用:

Debug.WriteLine("SetWaitState executing with Id={0}", AppDomain.CurrentDomain.Id)

MainForm.DataReady()本地事件处理程序的上下文中执行MainForm并且从ClassB调用时显示它们每次都在相同的AppDomain中运行。这留下了不同的线程作为问题的原因 - 然而MainForm.InvokeRequired在每种情况下都返回false。它仍然没有意义 - 但至少自定义事件 - 在必要时冒泡 - 确实有效。

下面的代码说明了这些关系。


Class MainForm
  private A as New ClassA

  private sub getData
    A.getData() 'Sets up the com object & callback
  end sub

  Private Sub _ClassB_HandleEvent(ResultMessage As String) Handles {some static/shared reference to ClassB}.CustomEvent
     'do something with the Message
  End Sub

End Class

Class ClassA

  public sub getData()
     Dim ComObj as New ComObject
     Call ComObj.setClient(New ClassB)
  End Sub

End Class

Class ClassB
  Implements IComObjectClient
  Public Event CustomEvent(ByVal ResultMessage As String)

  sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback
    ' Get the results
    RaiseEvent CustomEvent("Got Data") 'because calling MainForm.DataReady() doesn't work 
  end sub

End Class

2 个答案:

答案 0 :(得分:1)

或者忽略所有代表,并且只捕获A类中的B类事件,并提升您的Main Sub可以连接的新A类事件......

喜欢......

    Class MainForm
        private A As ClassA

        Public Sub _ClassB_HandleEvent(ByVal ResultMessage As String)
            ' Do Something like.... TextBox1.Text &= ("Received Event Saying - " & ResultMessage) & vbCrLf
        End Sub

        Private Sub GetData()
            A = New ClassA
            AddHandler A.GotDataFromClassB, AddressOf _ClassB_HandleEvent
            A.GetData()
        End Sub
    End Class

    Public Class ClassA
        Public Event GotDataFromClassB(ByVal ResultMessage As String)
        Private B As ClassB

        Public Sub GetData()
            B = New ClassB
            AddHandler B.CustomEvent, Sub(ResultMessage As String)
                                                RaiseEvent GotDataFromClassB(ResultMessage)
                                      End Sub
            Dim ComObj as New ComObject
            Call ComObj.setClient(B)
        End Sub
    End Class

Class ClassB
  Implements IComObjectClient
  Public Event CustomEvent(ByVal ResultMessage As String)

  sub getdata_callback(results() as Object) handles IComObjectClient.getdata_callback
    ' Get the results
    RaiseEvent CustomEvent("Got Data")
  end sub
End Class

答案 1 :(得分:0)

主窗体是否有某种方法可以监听ClassB的自定义事件的任何引发而不引用引发该事件的ClassB的特定实例?

你可以,但你必须

  1. 声明一个Public CustomEventHandler Delegate
  2. 声明一个ClassB变量,以便添加处理程序
  3. 将处理程序从MainFrom传递到A类
  4. e.g。

    Public Class MainForm
    
        Private Sub _ClassB_HandleEvent(ByVal ResultMessage As String)
          'do something with the Message
        End Sub
    
        Private A As New ClassA
    
        Public Sub getData()
    
            Dim eh As New ClassB.CustomEventHandler(AddressOf _ClassB_HandleEvent) 'create the delegate
            A.getData(eh) 'Pass it to ClassA
        End Sub
    End Class
    
    
    Public Class ClassA
    
        Public Sub getData(ByVal eh As ClassB.CustomEventHandler)
            Dim b As New ClassB
            AddHandler b.CustomEvent, eh
            Call setClient(b)
        End Sub
    
        Public Sub setClient(ByVal b As ClassB)
            b.getdata_callback()
        End Sub
    
    End Class
    
    Public Class ClassB
        Delegate Sub CustomEventHandler(ByVal ResultMessage As String) 'Declare the handler
        Public Event CustomEvent As CustomEventHandler
    
        Sub getdata_callback()
            RaiseEvent CustomEvent("Got Data")
        End Sub
    
    End Class