Групповые делегаты
В приведенных выше примерах в делегате инкапсулировался адрес одной функции или процедуры. Нередко в делегатах требуется инкапсулировать сразу несколько процедур (инкапсуляция нескольких функций особого смысла не имеет – каким должно быть возвращаемое значение?). Подобные делегаты называются групповыми (multicast) и реализуются в виде делегата, содержащего несколько однотипных делегатов. При наличии группового делегата все инкапсулированные процедуры вызываются одним методом Invoke, причем это происходит в соответствии с порядком занесения их делегатов в групповой делегат.
Чтобы создать групповой делегат, следует объединить минимум двух делегатов одного типа и присвоить результат переменной того же типа. Задача решается статическим методом Combine класса System.Delegate, который возвращает новый делегат.
Допустим, firstDel и secDel – экземпляры класса MyMultiCastDelegate. Следующая команда объединяет firstDel и secDel в групповой делегат, хранящийся в firstDel:
firstDel =System.Delegate.Combine(firstDel,secDel)
Ниже приведено простое приложение, объединяющее адреса нескольких функций в групповом делегате:
1 Option Strict On 2 Module Modulel 3 Sub Main() 4 Console.WriteLine("Calling delegate function…") 5 RegisterDelegate(AddressOf CallBackHandlerl) 6 RegisterDelegate(AddressOf CallBackHandler2) 7 Call Delegates () 8 Console.WriteLine( 9 "Finished calling.delegate function…") 10 Console.ReadLine() 11 End Sub 12 Public Sub CallBackHandlerHByVal lngVal As RETURNJALUES) 13 Console.WriteLine("Callback 1 returned " & IngVal) 14 End Sub 15 Public Sub CallBackHandler2(ByVallngVal As RETURNJALUES) 16 Console.WriteLine("Callback 2 returned " & IngVal) 17 End Sub 18 End Module 19 Module Module2 20 Public Delegate Sub CallBackFunc(ByVallngValAs RETURN_VALUES) 21 Private m_cbFunc As CallBackFunc 22 Public Enum RETURN_VALUES 23 VALUE_SUCCESS 24 VALUE_FAILURE 25 End Enum 26 Public Sub RegisterDelegate(ByRef cbFunc As CallBackFunc) 27 m_cbFunc = CType(System.Delegate.Combine(_ 28 m_cbFunc.cbFunc).CallBackFunc) 29 End Sub 30 Public Sub Call Delegates () 31 Dim IngCounter As Long = 0 32 ' Вызвать процедуры через делегата 33 ' и вернуть признак успешного вызова 34 m_cbFunc(RETURN VALUES.VALUE_SUCCESS) 35 End Sub 36 End Module
В строках 5 и 6 вызывается процедура модуля Module2 (строки 26-28), где и происходит фактическое построение группового делегата. Это возможно благодаря тому, что делегат передается по ссылке, а не по значению. Обратите внимание на преобразование типа метода Combine к типу делегата в строке 27. Непосредственный вызов функций группового делегата происходит в строках 30-35. Всем зарегистрированным функциям передается значение перечисляемого типа RETURNJALUES.VALUE_SUCCESS. Результат выполнения программы показан на рисунке.