КАТЕГОРИИ: Архитектура-(3434)Астрономия-(809)Биология-(7483)Биотехнологии-(1457)Военное дело-(14632)Высокие технологии-(1363)География-(913)Геология-(1438)Государство-(451)Демография-(1065)Дом-(47672)Журналистика и СМИ-(912)Изобретательство-(14524)Иностранные языки-(4268)Информатика-(17799)Искусство-(1338)История-(13644)Компьютеры-(11121)Косметика-(55)Кулинария-(373)Культура-(8427)Лингвистика-(374)Литература-(1642)Маркетинг-(23702)Математика-(16968)Машиностроение-(1700)Медицина-(12668)Менеджмент-(24684)Механика-(15423)Науковедение-(506)Образование-(11852)Охрана труда-(3308)Педагогика-(5571)Полиграфия-(1312)Политика-(7869)Право-(5454)Приборостроение-(1369)Программирование-(2801)Производство-(97182)Промышленность-(8706)Психология-(18388)Религия-(3217)Связь-(10668)Сельское хозяйство-(299)Социология-(6455)Спорт-(42831)Строительство-(4793)Торговля-(5050)Транспорт-(2929)Туризм-(1568)Физика-(3942)Философия-(17015)Финансы-(26596)Химия-(22929)Экология-(12095)Экономика-(9961)Электроника-(8441)Электротехника-(4623)Энергетика-(12629)Юриспруденция-(1492)Ядерная техника-(1748) |
MulticastDelegate.GetInvocationList
Delegate.Invoke или что там внутри? Напомним, как выглядит механизм вызова делегата через обращение к методу Invoke.
Программистам, использующим языки высокого уровня, это может показаться странным, поскольку на их уровне обращение к делегату происходит как к обычной функции.
Дело в том, что метод Invoke недокументирован. Он не является членом классов Delegate и MulticastDelegate. Соответственно, можно предположить, что это специальный метод, генерируемый компилятором. Для проверки предположения обратимся к IL-коду. Действительно, там обнаружится метод Invoke, его код приведен ниже.
Его изучение показывает, что метод лишен какого-либо кода. Он попросту пустой и ничего не может делать. Так может показаться, если не принимать во внимание спецификатор runtime, используемый при определении метода. Данный спецификатор указывает на то, что метод будет реализован по ходу исполнения программы самой средой исполнения. Это означает, что код, обрабатывающий вызов метода, располагается в недрах самой среды исполнения. А она прекрасно осведомлена о внутреннем устройстве делегата и справится с вызовом всех его методов без дополнительной помощи со стороны программиста. Помимо этого можно отметить, что конструктор каждого делегата описывается подобным образом. Для примера приведем код конструктора одного из делегатов.
Код, реализующий делегат, также находится внутри среды исполнения. Оказывается, метод Invoke отвечает не только за вызов делегата, но также за хранение информации о прототипе методов, на которые может ссылаться делегат. Не правда ли, изящное решение? Прототип закодирован в самом методе Invoke, то есть его прототип полностью совпадает с прототипом делегата. Таким образом, не надо прибегать к использованию дополнительных средств, вроде MethodInfo, для хранения информации о прототипе. К тому же, это страхует от возможности случайной передачи неверного количества или типа параметров при классическом обращении к делегату. Возвращает список делегатов, находящихся в списке вызовов делегата.
Несмотря на кажущуюся абстрактность метода, он имеет очень важное практическое применение. Существует два недостатка механизма вызова функций, связанных с делегатом. И оба они связаны со случаем, когда в списке вызова делегата присутствует более одной функции. § Функции, на которые ссылаются делегаты, могут возвращать значения. Но мы их получить не сможем, поскольку штатная функция вызова Invoke возвращает значение, которая вернула последняя из опрошенных функций. § При обращении к делегату, содержащему в списке вызова несколько функций, вовсе не гарантируется, что все функции из списка будут вызваны. Если одна из них сгенерирует исключение, то работа метода Invoke будет прервана и остальные функции вызваны не будут. Особое волнение вызывает вторая проблема, поскольку важные сообщения попросту могут не дойти до адресата. Что неприемлемо при разработке надежных систем. Рассмотрим пример (листинг 9). Листинг 9. Демонстрация ненадежности делегатов, ссылающихся на несколько функций
В результате работы программы на консоль будут выведены следующие строки.
Таким образом, исходя из информации, представленной в логе, нетрудно понять, что в список вызова делегата было добавлено два метода, но вызван был только первый из них. Надеюсь, причины такого поведения программы понятны. Обойти проблему можно следующим образом. Для этого придется воспользоваться методом GetInvocationList, чтобы организовать обращение к делегатам полностью в ручном режиме. Преимущество подхода заключается в том, что можно полноценно контролировать обращение к каждому методу, на который ссылается делегат. Код примера вы обнаружите в листинге 10. Листинг 10. Надежный способ работы с делегатами, ссылающимися на несколько методов.
В результате работы программы на консоль будут выведены следующие строки.
Видно, что задачи, поставленные перед приложением, были успешно выполнены. Несмотря на то, что в одной из функций, на которую ссылался делегат, было выброшено исключение, это не отразилось на работе остальных функций. Помимо кода, обрабатывающего исключения, можно добавить специальные сервисы, анализирующие значения, возвращаемые функциями, вызываемыми через делегат. Отметим, что обращаться к методам можно не только через функцию DynamicInvoke. Для этих целей также можно использовать свойство Method. А точнее, метод Invoke, предоставляемый классом MethodInfo, экземпляр которого можно получить через вышеупомянутое свойство класса Delegate. В итоге, код вызова можно заменить следующим:
Особую практическую пользу в этом подходе найти, конечно, сложно, особенно учитывая его медлительность. Но зато вы будете всегда иметь запасной вариант при работе с делегатами.
Дата добавления: 2014-01-07; Просмотров: 402; Нарушение авторских прав?; Мы поможем в написании вашей работы! Нам важно ваше мнение! Был ли полезен опубликованный материал? Да | Нет |