2016-06-10 5 views
2

Я знаю, что в VB .Net можно определить свой пользовательский обработчик событий.Различные способы повышения пользовательского события в .NET Framework

Это способ для класса узнать, когда другой слушает его события. Этот пример кода происходит от MSDN:

Private Events As EventHandlerList 

Public Custom Event MyEvent As EventHandler 
    AddHandler(value As EventHandler) 
     Events.AddHandler("Test", value) 
    End AddHandler 

    RemoveHandler(value As EventHandler) 
     Events.RemoveHandler("Test", value) 
    End RemoveHandler 

    RaiseEvent(sender As Object, e As EventArgs) 
     CType(Events("Test"), EventHandler).Invoke(sender, e) 
    End RaiseEvent 
End Event 

Теперь, это то, как вы можете поднять пользовательское событие:

Private Sub MySub() 
    RaiseEvent MyEvent(Me, EventArgs.Empty) 
End Sub 

До сих пор так хорошо, никаких проблем вообще.

Мой вопрос в том, что в моем классе у меня есть прямой доступ к EventHandlerList, могу ли я вызвать его вне настраиваемого обработчика событий? И если да, то есть ли разница между тем, что этот суборд делает из того, что выше?

Private Sub MySub2() 
    CType(Events("Test"), EventHandler).Invoke(Me, EventArgs.Empty) 
End Sub 

Я знаю, что это, вероятно, нет хороших привычек на всех, я просто любопытно, как я могу иметь функцию, которая передается название события, как String так, что путь повышения событие могло бы работать для меня, я бы сделать что-то вроде:

Private Sub RaiseCustomEvent(EventName As String, Ev as EventArgs) 
    CType(Events(EventName), EventHandler).Invoke(Me, Ev) 
End Sub 
+0

Этот пример MSDN основан на значении ключа ('String'), которое будет [Interned] (https://msdn.microsoft.com/en-us/library/system.string.isinterned (v = vs 0,110) .aspx). Ключевым аргументом является тип 'Object', а свойство' EventHandlerList.Item' использует ссылочное равенство при поиске запрашиваемого обработчика, а не сравнительного сравнения по умолчанию для базового типа. Было бы лучше явно объявить ключ, т. Е. «Private MyEventKey As New Object».Кроме того, вы должны проверить, что результат «События (EventName)» не является чем-то другим, прежде чем пытаться вызвать 'Invoke'. – TnTinMn

+0

Также будьте осторожны, если вы добавите настраиваемое событие в класс Form и 1) объявите новый «EventHandlerList» для хранения событий и 2) впоследствии присоедините обработчик событий через VS IDE, который создает метод с предложением 'Handles'. Из-за того, как работает компилятор VB, сгенерированный код будет пытаться добавить обработчик событий в «EventHandlerList» до создания экземпляра «EventHandlerList». Это приводит к исключению нулевой ссылки при создании формы. – TnTinMn

ответ

3

Мой вопрос, так как в моем классе у меня есть прямой доступ к EventHandlerList, я могу назвать его пределами пользовательского обработчика событий?

Да.

И если да, есть ли разница между тем, что этот суборд делает из одного выше?

Нет. Инструкция RaiseEvent просто вызывает часть RaiseEvent объявления вашего события. Спецификация VB.NET говорит:

Объявление RaiseEvent принимает те же параметры, что и делегат события, и будет вызываться при выполнении инструкции RaiseEvent.

Заметим, однако, что пример MSDN сломана --- это поднимает NullReferenceException если обработчик событий не прилагается (Fiddle):

Public Module Module1 
    Public Sub Main() 
     Dim x As New T() 
     x.RaiseTestEvent() 
    End Sub 
End Module 

Public Class T 
    Private Events As New System.ComponentModel.EventHandlerList() 

    Public Custom Event MyEvent As EventHandler 
     AddHandler(value As EventHandler) 
      Events.AddHandler("Test", value) 
     End AddHandler 

     RemoveHandler(value As EventHandler) 
      Events.RemoveHandler("Test", value) 
     End RemoveHandler 

     RaiseEvent(sender As Object, e As EventArgs) 
      CType(Events("Test"), EventHandler).Invoke(sender, e) 
     End RaiseEvent 
    End Event 

    Public Sub RaiseTestEvent() 
     ' Throws NullReferenceException if no event handler is attached. 
     RaiseEvent MyEvent(Me, EventArgs.Empty) 
    End Sub 
End Class 

Для «обычных» событий, RaiseEvent просто NO-OP, если обработчик не подключен (Fiddle). Спецификация VB говорит:

Оператор RaiseEvent обрабатывается как вызов метода Invoke делегата события, используя предоставленные параметры, если таковые имеются. Если значение делегата равно Nothing, исключение не будет выбрано.

+0

Благодарим вас за эти замечания –

Смежные вопросы