День пятидесятый. #ЗаметкиНаПолях
Управление цепочками делегатов
В C# можно создавать и управлять цепочками делегатов при помощи операторов
В качестве альтернативы можно использовать метод
Управление цепочками делегатов
В C# можно создавать и управлять цепочками делегатов при помощи операторов
+=
и -=
. Цепочку делегатов можно вызвать так же, как и единичный делегат. При этом будут вызваны все делегаты цепочки по очереди. Это достаточно удобно и подходит для большинства сценариев. Однако у этого метода есть ряд ограничений. Например, сохраняется только последнее из возвращаемых значений, возвращаемых методами. Получить остальные значения нельзя. Кроме того, если один из делегатов в цепочке выбрасывает исключение, работа цепочки останавливается.В качестве альтернативы можно использовать метод
GetInvokationList
класса MulticastDelegate
. Он возвращает массив ссылок на делегаты в цепочке. Следующий код безопасно выполняет делегаты из цепочки и сохраняет их возвращаемые значения:private delegate string MyDelegate();Источник: Джеффри Рихтер “CLR via C#”. 3-е изд. – СПб.: Питер, 2012. Глава 17.
private static string Method1() => "Method1";
private static string Method2() => throw new Exception("Exception");
private static string Method3() => "Method3";
static void Main(string[] args)
{
MyDelegate getResult = null;
getResult += new MyDelegate(Method1);
getResult += new MyDelegate(Method2);
getResult += new MyDelegate(Method3);
Console.WriteLine(GetAllResults(getResult));
}
private static string GetAllResults(MyDelegate result)
{
if (result == null) return null;
var report = new StringBuilder();
var delegates = result.GetInvocationList();
foreach (MyDelegate del in delegates)
{
try
{
//пытаемся выполнить метод, сохраняя его результат
report.AppendFormat("{0}\n", del());
}
catch (Exception ex)
{
//обрабатываем ошибки метода
//здесь component – класс владелец метода
var component = del.Target;
report.AppendFormat(
" Ошибка при получении результата из метода {0}{1}: {2}\n",
((component == null) ? "" : component.GetType() + "."),
del.Method.Name,
ex.Message);
}
}
return report.ToString();
}