Cамоучитель по VB.NET

       

Динамическая обработка событий




Основной проблемой синтаксиса WithEvents является его недостаточная гибкость. Обработчики событий нельзя динамически устанавливать и отключать на программном уровне — фактически вся схема обработки событий жестко фиксируется в программе. Однако в VB .NET поддерживается другой способ динамической обработки событий, значительно более гибкий. Он основан на возможности указания процедуры класса-приемника, вызываемой при возникновении события (исключение добавленных обработчиков также происходит динамически).

Конечно, для установки обработчика события необходимо зарегистрировать не только класс-приемник, но и метод, который должен вызываться при возникновении события. Для этой цели применяется команда AddHandler, которой при вызове передаются два параметра:

  • имя события в классе-источнике;
  • адрес метода (процедуры событий) класса-приемника, вызываемого при возникновении события.

Код AddHandl ег включается в класс-приемник, а не в класс-источник. Адрес метода, вызываемого при возникновении события, определяется оператором AddressOf. При вызове AddressOf передается имя метода объекта класса-приемника. Например, следующая команда устанавливает динамический обработчик события для объекта

tom:

AddHandler tom.SalarySecurityEvent.AddressOf anEmp1oyee_SalarySecurityEvent

В результате тестовая программа будет обнаруживать событие Sal arySecuri tyEvent объекта tom и в случае его возникновения — вызывать процедуру anEmployee_SalarySecurityEvent текущего модуля (разумеется, процедура anEmployee_SalarySecurityEvent должна обладать правильной сигнатурой!).

Ниже приведен фрагмент решения AddHandlerExamplel (ключевые строки выделены жирным шрифтом):

Module Modulel

Private WithEvents anEmployee As EmployeeWithEvents Sub Main()

Dim torn As New EmployeeWithEvents("Tom". 100000)

Console.WriteLine(tom.TheName & "has salary " & tom.Salary)

AddHandler tom.SalarySecurityEvent,

AddressOf anEmployee_SalarySecurityEvent

tom.RaiseSalary(0.2D) ' Суффикс D - признак типа Decimal

Console.WriteLine(tom.TheName & "still has salary " & tom.Salary)

Console.WriteLine("Please press the Enter key")

Console. ReadLine()

End Sub

Public Sub anEmployee_SalarySecurity£vent(ByVal Sender _

As AddHandlerExamplel.EmployeeWi thEvents,_

ByVal e As AddHandlerExamplel.ImproperSalaryRaiseEvent)_

Handles anEmployee.SalarySecurityEvent

MsgBox(Sender.TheName & "had an improper salary raise of " & _

FormatPercent(e.theRaise) & "with INCORRECT PASSWORD!")

End Sub

End Module

Команда AddHandler обладает просто невероятной гибкостью. Например, установка обработчиков событий может зависеть от имени типа:

If TypeName(tom)="Manager" Then

AddHandler tom.SalarySecurityEvent.AddressOf _

anEmployee_SalarySecurityEvent e

End If

Кроме того, один обработчик событий можно связать с несколькими разными событиями, происходящими в разных классах. Это позволяет выполнять в VB .NET централизованную обработку событий с динамическим назначением обработчиков — в VB такая возможность встречается впервые. В приведенном ниже листинге инициируются разные события в зависимости от переданных параметров командной строки. Главное место в нем занимают фрагменты вида

Case "first"

AddHandler m_EventGenerator.TestEvent,_

AddressOf m_EventGenerator_TestEventl

При передаче в командной строке аргумента first устанавливается соответствующий обработчик события.

В программе используется полезный метод GetCommandLineArgs класса System.Environment. Как упоминалось в главе 3, этот метод возвращает массив аргументов командной строки. Начальный элемент массива содержит имя исполняемого файла; поскольку индексация массива начинается с 0, для получения первого аргумента используется вызов System.Environment.GetComman3LineArgs(l), однако предварительно необходимо убедиться в существовании аргументов командной строки, для чего проверяется длина массива System.Environment.GetCommandLineArgs. Перед запуском программы перейдите на страницу Configuration Properties диалогового окна Project Properties и укажите аргументы командной строки для тестирования.

Ниже приведен полный исходный текст программы:

Option Strict On Module Modulel

Private m_EventGenerator As EventGenerator

Sub Main()

m_EventGenerator= New EventGenerator()

Dim commandLinesOAs String = System.Environment.GetCommandLineArgs

If commandLines.Length = 1 Then

MsgBox("No command argument.program ending!")

Environment.Exit(-l) Else

Dim theCommand As String = commandLines(l)

Console.WriteLine("Thecommand lineoption is" StheCommand)

' Проверить параметр командной строки и назначить

' соответствующий обработчик события.

Select Case theCommand Case "first"

AddHandler m_EventGenerator.TestEvent. AddressOf

m_EventGenerator_TestEvent1

Case "second"

AddHandler m_EventGenerator.TestEvent,_ AddressOf

m_EventGenerator_TestEvent2

Case Else

AddHandler m_EventGenerator.TestEvent. AddressOf

m_EventGenerator_TestEventDefault

End Select

' Инициировать события

m_EventGenerator.TriggerEvents()

End If

Console.WriteLine("Press enter to end.")

Console. ReadLine()

End Sub

'Обработчик по умолчанию для непустой командной строки

Public Sub m_EventGenerator_TestEventDefault(_

ByVal sender As Object.ByVal evt As EventArgs) System.Console.WriteLine("Default choice " & _

m_EventGenerator.GetDescri pti on()) End Sub

' Обработчик 12 для строки "first"

Public Sub m_EventGenerator_TestEvent1(_

ByVal sender As Object.ByVal evt As EventArgs)

System.Console.WriteLineC'lst choice " & _

m_EventGenerator.GetDescription()) End Sub

'Обработчик 13 для строки "second"

Public Sub m_EventGenerator_TestEvent2(

ByVal sender As Object.ByVal evt As EventArgs)

System.Console.WriteLinet"2nd choice " & _

m_EventGenerator.GetDescri pti on ())

End Sub

End Module

Public Class EventGenerator

' В классе определяется только одно событие

Public Event TestEvent(ByVal sender As Object, ByValevt As EventArgs)

' Также можно было использовать конструктор по умолчанию

Public Sub New()

' Пустой конструктор

End Sub

.Public Function GetDescription() As String

Return "EventGenerator class"

End Function

' Процедура вызывается для инициирования событий

Public Sub TriggerEvents()

Dim e As System.EventArgs = New System.EventArgs()

RaiseEvent TestEvent(Me.e)

End Sub

End Class





Содержание раздела