Динамическая обработка событий
Основной проблемой синтаксиса WithEvents является его недостаточная гибкость. Обработчики событий нельзя динамически устанавливать и отключать на программном уровне – фактически вся схема обработки событий жестко фиксируется в программе. Однако в VB.NET поддерживается другой способ динамической обработки событий, значительно более гибкий. Он основан на возможности указания процедуры класса-приемника, вызываемой при возникновении события (исключение добавленных обработчиков также происходит динамически).
Конечно, для установки обработчика события необходимо зарегистрировать не только класс-приемник, но и метод, который должен вызываться при возникновении события. Для этой цели применяется команда AddHandler, которой при вызове передаются два параметра:
- имя события в классе-источнике;
- адрес метода (процедуры событий) класса-приемника, вызываемого при возникновении события.
Код AddHandlег включается в класс-приемник, а не в класс-источник. Адрес метода, вызываемого при возникновении события, определяется оператором AddressOf. При вызове AddressOf передается имя метода объекта класса-приемника. Например, следующая команда устанавливает динамический обработчик события для объекта:
tom: AddHandler tom.SalarySecurityEvent.AddressOf anEmp1oyee_SalarySecurityEvent
В результате тестовая программа будет обнаруживать событие SalarySecurityEvent объекта 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,_ ByVale 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 устанавливается соответствующий обработчик события.