2012-07-11 96 views
0

我有一個MyCol類,它繼承自ObservableCollection(Of T)。它覆蓋InsertItem方法,以這樣一種方式:如何正確覆蓋引發事件的方法

Public Event PreInsertItem As EventHandler(Of EventArgs) 

Protected Overridable Sub OnPreInsertItem(e As EventAtgs) 
    RaiseEvent PreInsertItem(Me, e) 
End Sub 

Protected Overrides Sub InsertItem(index As Integer, item As T) 
    OnPreInsertItem(EventArgs.Empty) 

    MyBase.InsertItem(index, item) 
End Sub 

正如你可以看到我已經添加了被提出的每一個項目添加到MyCol收集時間的事件。

接着我創建另一個類MyColSubClass,它從MyCol繼承,並且還覆蓋InsertItem方法:

Public Overrides Sub InsertItem(index as Integer, item as T) 
    OnPreInsertItem(EventArgs.Empty) 

    ' some additional code goes here 

    MyBase.InsertItem(index, item) 
End Sub 

的問題是:

現在,當我使用MyColSubClass的一個實例,並添加項目,PreInsertItem事件被引發兩次:第一次在MyColSubClass和比MyCol。

我應該使用什麼設計模式來使PreInsertItem事件只會引發一次:在MyColSubClass中?

N.B.

示例中顯示的類和事件從現實生活應用程序中簡化了,但假設它們顯示了確切的應用程序結構。在最後的繼承類中提高事件是必須的。

+0

爲什麼要從子類調用'OnPreInsertItem(EventArgs.Empty)'?當你執行'MyBase.InsertItem(index,item)'時,它已經被調用了。 – LarsTech 2012-07-11 12:03:43

+0

這裏我展示了一個簡化的例子。在實際應用中,很多數據都在事件數據中傳遞。所以必須在每個繼承的類中調用事件(即MyColSubClass)。 – Dima 2012-07-11 12:08:21

回答

1

如果您確實知道基類會引發該事件,那麼在派生類中這樣做毫無用處。

只要改變你的覆蓋到:

Public Overrides Sub InsertItem(index as Integer, item as T) 
    ' some additional code goes here 

    MyBase.InsertItem(index, item) 
End Sub 

這應該是罰款。

但是,如果你改變你的衍生方法,並停止調用MyBase.InsertItem(...),你應該在提高你的覆蓋情況,以確保它被提出:

Public Overrides Sub InsertItem(index as Integer, item as T) 
    ' some additional code goes here 

    OnPreInsertItem(EventArgs.Empty) 

    ' insert your item and do whatever... 
End Sub 

編輯

如果您需要更改事件引發的方式,但要確保它只被暫時上升,簡單地覆蓋在派生類中的方法OnPreInsertItem:

Protected Overrides Sub OnPreInsertItem(e as EventArgs) 
    ' Do wahetever you need here, change e, add info, whatever... 
    ' ... 
    ' Then raise the event (or call MyBase.OnPreInsertItem, as you like) 
    RaiseEvent PreInsertItem(Me, e) 
End Sub 

Public Overrides Sub InsertItem(index as Integer, item as T) 
    ' some additional code goes here 

    ' This will work only if MyBase.InsertItem calls OnPreInsertItem. 
    ' Otherwise, you have to handle the insertion and raise the event 
    ' yourself without calling the base method. 
    MyBase.InsertItem(index, item) 
End Sub 

由於OnPreInsertItem是可重寫的,所以當您在派生類中插入項目時,派生類中的版本將被調用。

希望幫助:)

+0

我的問題中有一個簡化的例子。在真正的應用程序中,我必須在任何附加代碼之前引發事件,因爲事件傳遞了大量數據(再次,在實際應用程序中)。 – Dima 2012-07-11 12:09:42

+0

您上次編輯的絕佳解決方案!謝謝,真的有幫助,不知道我自己錯過了:) – Dima 2012-07-11 12:21:21

+0

不客氣:) – 2012-07-11 12:23:03

0

我不認爲你應該在你的子類MyColSubClass提高OnPreInsertItem
你的方法應該是這樣的:

Public Overrides Sub InsertItem(index as Integer, item as T) 
    ' some additional code goes here 

    MyBase.InsertItem(index, item) 
End Sub 

你延長你的基類的一些功能。 如果要更換特定的功能,那麼你的方法應該是這樣的:

Public Overrides Sub InsertItem(index as Integer, item as T) 
    OnPreInsertItem(EventArgs.Empty) 

    ' some additional code goes here 

End Sub 

你可以找到更多的相關信息herehere

0

如果我知道了,你想在不同級別的繼承中向EventArg類添加信息。在這種情況下,提供與引發事件相同級別的EventArg成員在我看來是最好的解決方案,而InsertItem()的所有重寫只是修改此EventArg成員,而事件跟隨此事件引發的事件只會在最高可能情況下引發水平。

相關問題