2016-05-14 17 views
1

給定兩個具有相同事件的類,我希望能夠使用一個名稱來引用它們。類似以下內容:如何在運行時使用相同的事件附加到不同的類?

Public Class myclass1 
    Public event1() 
End Class 

Public Class myclass2 
    Public event1() 
End Class 

在這裏,我想能夠在運行時確定使用哪個類:

Sub somefunction(select as integer) 
    Dim voidclass 
    if select = 1 then 
     voidclass = myclass1 
    else 
     voidclass = myclass2 
    end if 
    AddHandler voidclass.event1, AddressOf eventhappened 
End Sub 

Sub eventhappened() 
    msgbox("Event occured") 
End Sub 

顯然有可能是這個例子更好的方法,但讓我們假定類book1已經存在,並且我的任務是創建book2並且只修改somefunction而不修改book1本身。

上面的例子應該會導致錯誤event1不是'Object'`的事件。

看來,屬性和方法都很好,但事件不是。我在這種情況下如何處理事件?

+0

與'GetType()'比較結合怎麼樣?或者創建其他類派生自的基類,其中基類包含事件。然後你可以投到基類。 –

回答

1

您可以爲事件定義一個接口並在類中實現它,然後您可以通過接口引用來訂閱此事件。見下:

Public Interface INotifier 
    Event SomethingHappened() 
End Interface 

Public Class Class1 
    Implements INotifier 

    Public Event SomethingHappened() Implements INotifier.SomethingHappened 
End Class 

Public Class Class2 
    Implements INotifier 

    Public Event SomethingHappened() Implements INotifier.SomethingHappened 
End Class 

Module Module1 

    Dim notifiers As List(Of INotifier) = New List(Of INotifier) From 
    { 
     New Class1(), 
     New Class2() 
    } 

    Sub Main() 
     SubscribeToEventHandler(0) 
    End Sub 

    Private Sub SubscribeToEventHandler(ByVal index As Integer) 
     Dim notifier As INotifier = notifiers(index) 
     AddHandler notifier.SomethingHappened, AddressOf EventHandler 
    End Sub 

    Private Sub EventHandler() 

    End Sub 

End Module 
2

該片段不符合問題很好。它有一個奇怪的錯誤,類中的事件沒有被聲明爲Shared,因此代碼必須使用適當的對象引用。不是類型名稱。也許答案很簡單:

Private obj1 As myclass1 
    Private obj2 As myclass2 

    Sub somefunction(select as integer) 
     If select = 1 Then 
      AddHandler obj1.event1, AddressOf eventhappened 
     Else 
      AddHandler obj2.event1, AddressOf eventhappened 
     End If 
    End Sub 

但據推測,真正的問題是同樣的情況,但現在宣佈爲變量:

Private obj1, obj2 

非類型化,從而Object。是的,VB.NET不支持。就像VB.NET中的大多數怪癖一樣,背後有這樣的歷史。 VB從來沒有支持顯式的事件後期綁定,只有方法和屬性。傳統版本中的方案非常古怪。您必須用WithEvents關鍵字聲明變量併爲事件處理程序選擇一個特定的名稱。換句話說:

Dim WithEvents obj1 

    Sub obj1_somethinghappened 
     '' handles the event1 event for obj1 
    End Sub 

或換句話說,所有事件都是遲到的。這個方案沒有推廣到VB.NET中,它有太多的實際問題。 WithEvents仍然存活,但現在需要方法聲明中的Handles關鍵字。這不符合你想要的。

VB.NET設計者故意沒有爲AddHandler語句添加後期綁定支持。我不知道他們決定這一點的確切原因,只能猜測。沒有技術上的原因,它不能被添加,它只是要求編譯器生成反射代碼。一個可能的解釋是他們認爲它太昂貴了。另一個是他們認爲當方法簽名不匹配太難解釋時引發運行時異常。我最喜歡最後一個,他們非常難看。

你將不得不使用反射來得到你想要的。使用obj1.GetType().GetEvent(「event1」)來獲取EventInfo,它的Get/AddMethod()來添加事件處理程序。

Fwiw,C#語言在其動態關鍵字實現中確實支持這一點。也許你可以通過asking for the feature在他們的耳朵裏發現一個bug。沒有真正的想法,如果這是以前的要求。

相關問題