foreach (Delegate d in delObj.GetInvocationList())
{
Console.WriteLine("Method Name: {0}", d.Method); // имя метода
Console.WriteLine("Type Name: {0}", d.Target); // имя типа
}
}
Предполагая, что в метод Main() добавлен вызов нового вспомогательного метода:
BinaryOp b = new BinaryOp(SimpleMath.Add);
DisplayDelegateInfo(b);
вывод приложения будет таким:
***** Simple Delegate Example *****
Method Name: Int32 Add(Int32, Int32)
Type Name:
10 + 10 is 20
Обратите внимание, что при обращении к свойству Target имя целевого класса (SimpleMath) в настоящий момент не отображается. Причина в том, что делегат BinaryOp указывает на Add() и Substract() нестатическими (удалив ключевое слово static из их объявлений), тогда можно будет создавать экземпляр класса SimpleMath и указывать методы для вызова с применением ссылки на объект:
using System;
using SimpleDelegate;
Console.WriteLine("***** Simple Delegate Example *****\n");
// Делегаты могут также указывать на методы экземпляра.
SimpleMath m = new SimpleMath();
BinaryOp b = new BinaryOp(m.Add);
// Вывести сведения об объекте.
DisplayDelegateInfo(b);
Console.WriteLine("10 + 10 is {0}", b(10, 10));
Console.ReadLine();
В данном случае вывод будет выглядеть следующим образом:
***** Simple Delegate Example *****
Method Name: Int32 Add(Int32, Int32)
Type Name: SimpleDelegate.SimpleMath
10 + 10 is 20
Отправка уведомлений о состоянии объекта с использованием делегатов
Очевидно, что предыдущий пример SimpleDelegate был чисто иллюстративным по своей природе, т.к. нет особых причин создавать делегат просто для того, чтобы сложить два числа. Рассмотрим более реалистичный пример, в котором делегаты применяются для определения класса Car, обладающего способностью информировать внешние сущности о текущем состоянии двигателя. В таком случае нужно выполнить перечисленные ниже действия.
1. Определить новый тип делегата, который будет использоваться для отправки уведомлений вызывающему коду.
2. Объявить переменную-член этого типа делегата в классе Car.
3. Создать в классе Car вспомогательную функцию, которая позволяет вызывающему коду указывать метод для обратного вызова.
4. Реализовать метод Accelerate() для обращения к списку вызовов делегата в подходящих обстоятельствах.
Для начала создайте новый проект консольного приложения по имени CarDelegate. Определите в нем новый класс Car, начальный код которого показан ниже:
using System;
using System.Linq;
namespace CarDelegate
{
public class Car
{
// Внутренние данные состояния.
public int CurrentSpeed { get; set; }
public int MaxSpeed { get; set; } = 100;
public string PetName { get; set; }
// Исправен ли автомобиль?
private bool _carIsDead;
// Конструкторы класса.
public Car() {}
public Car(string name, int maxSp, int currSp)
{
CurrentSpeed = currSp;
MaxSpeed = maxSp;
PetName = name;
}
}
}
А теперь модифицируйте его, выполнив первые три действия из числа указанных выше:
public class Car
{
...
// 1. Определить тип делегата.
public delegate void CarEngineHandler(string msgForCaller);
// 2. Определить переменную-член этого типа делегата.
private CarEngineHandler _listOfHandlers;
// 3. Добавить регистрационную функцию для вызывающего кода.
public void RegisterWithCarEngine(CarEngineHandler methodToCall)
{