使用GetInvocationList对委托链进行更多的控制
委托链中所有项都会被调用,因为委托类型的 Invoke 方法包含了对数组中的所有项进行遍历的代码。这是一个很简单的算法。尽管这个简单的算法足以应付很多情形,但也有它的局限性。例如,除了最后一个返回值,其他所有回调方法的返回值都会被丢弃。但局限并不止于此。如果被调用的委托中有一个抛出了异常或阻塞了相当长一段时间,会出现什么情况呢?由于这个简单的算法是顺序调用链中的每一个委托,所以一个委托对象出现问题,链中后续的所有对象都调用不了啊。显然,这个算法还不够健壮性。
所以 MulticastDelegate(派生于 Delegate)类提供了一个实例方法 GetInvocationList,用于显式调用链中的每一个委托,并允许你使用需要的任何算法。
GetInvocationList 方法操作从 MulticastDelegate 派生的对象,返回包含 Delegate 引用的一个数组,其中每个引用都指向链中的一个委托对象。在内部,GetInvocationList 构造并初始化一个数组,让它的每个元素都引用链中的一个委托,然后返回对该数组的引用。如果 _invocationList 字段为null,返回的数组就只有一个元素,该元素引用链中唯一的委托,即委托实例本身。
如下代码演示:
using System;
using System.Text; namespace _17._5._2取得对委托链调用的更多控制
{
class Program
{
// 定义委托来查询一个组件的状态
private delegate string GetStatus(); static void Main(string[] args)
{
// 声明空委托链
GetStatus getStatus = null; // 构造3个组件,将它们的状态方法添加到委托链中
getStatus += new GetStatus(new Light().SwitchPosition);
getStatus += new GetStatus(new Fan().Speed);
getStatus += new GetStatus(new Speaker().Volume); // 显式整理好的状态报告,反映这3个组件的状态。
Console.WriteLine(GetComponentStatusReport(getStatus)); Console.ReadKey();
} // 该方法查询几个组件并返回状态报告
private static string GetComponentStatusReport(GetStatus status)
{
// 如果委托链为空,就不进行任何操作
if (status == null) return null; // 用下面的变量来创建状态报告
StringBuilder report = new StringBuilder(); // 获得一个数组,其中每个元素都是链中的委托
Delegate[] arrayOfDelegates = status.GetInvocationList(); // 遍历数组中每一个委托
foreach (GetStatus getStatus in arrayOfDelegates)
{
try
{
// 获得一个组件的状态字符串
report.AppendFormat("{0}{1}{1}", getStatus(), Environment.NewLine);
}
catch (InvalidOperationException e)
{
// 在状态报告中为该组件生成一个错误记录。
object component = getStatus.Target; report.AppendFormat(
"Failed to get status from {1}{2}{0} Error: {3}{0}{0}",
Environment.NewLine,
((component == null) ? "" : component.GetType() + "."),
getStatus.Method.Name,
e.Message);
}
} return report.ToString();
}
} // 定义一个灯组件
internal sealed class Light
{
// 该方法返回灯的状态
public string SwitchPosition()
{
return "The light is off";
}
} // 定义一个风扇组件
internal sealed class Fan
{
// 该方法返回风扇组件
public string Speed()
{
throw new InvalidOperationException("The fan broke due to overheating");
}
} // 定义一个扬声器组件
internal sealed class Speaker
{
// 该方法返回扬声器的状态
public string Volume()
{
return "The volume is loud";
}
}
}
使用GetInvocationList对委托链进行更多的控制的更多相关文章
- 链方法[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链
最近研究链方法,稍微总结一下,以后继续补充: 弁言: 上一专题分析了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的分析都是委托只是封装一个方法,那委 ...
- [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)
引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...
- .net委托链
委托链可以增加方法,可以移除方法,如果是无返回值的方法,我们把它们都绑定到一个委托上面的话,直接调用,那么调用此委托就会依次调用其中的方法:但是如果是多个有返回值的委托链,如果我们不采用特殊手段,直接 ...
- 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理
委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...
- C#.NET常见问题(FAQ)-delegate委托链如何使用
委托链本质就是你把一堆要执行的东西放到一个list里面,当要触发一组事情的时候,就不需要一个一个写一遍了(比如厂里食堂开饭了,这个方法一执行,要让厨师A时间在食堂等候打饭,B类员工在某个时间排队打饭, ...
- 委托Delegate,多播委托和委托链
定义一个委托 public delegate void CalculateDelegate(int 32 x,int 32 y); 定义一个委托类型的变量 public static Calculat ...
- JavaScript和JQuery中的事件\委托链\事件冒泡\事件捕获,兼容所有浏览器
有做过北大青鸟培训讲师经验的我,如今在一家公司做技术部经理的职位,发现有很多程序员的基本功相当糟糕,在组织企业内部培训时讲解了一些案例,总结了一些经典代码,希望对自己和有需要的人提供一些帮助吧: Ja ...
- C# 委托之把委托从委托链(多播委托)移除
运用“-”运算符将委托从委托链移除 class HelloWorld { //定义委托类型 delegate void DelegationChain(); static void Main(stri ...
- C# 委托链、多路广播委托
委托链.多路广播委托:也就是把多个委托链接在一起,我们把链接了多个方法的委托称为委托链或多路广播委托 例: class HelloWorld { //定义委托类型 delegate void Dele ...
随机推荐
- Linux命令(文本编辑器)
vi和vim编辑器:有插入模式,一般模式,地行模式 一班模式通过(i.a.o.I.A.O)键--->进入插入模式 插入模式(按Esc键退出)---->j进入一班模式 ...
- PHP 魔术方法浅谈
php中把以两个下划线(__)开头的方法称之为魔术方法.魔术方法包括: __construct() 类的构造方法 构建方法时被调用 __destruct() 类的析构方法 明确销毁 ...
- The JVM Architecture Explained
转自:https://dzone.com/articles/jvm-architecture-explained?oid=18544920 Every Java developer knows tha ...
- SDOI2018退役记
在NOIp2017中,我意识到自己啥也不会.如今SDOI2018快来了,自己还是啥也不会.高一两次考试注定以打两次酱油告终.还是记录一下,到NOIp之后如果还没有退役的话,那这个博客可能还会继续更新吧 ...
- 求n!(高精度问题)
#include <iostream> #include <stdio.h> #define MAX 10000 using namespace std; void Mul(i ...
- MySQL(端口3306)
MySQL(二进制)安装: 下载地址:http://dev.mysql.com/get/Downloads/MySQL-5.5/mysql-5.5.49-linux2.6-x86_64.tar.gz ...
- Python爬虫基础--分布式爬取贝壳网房屋信息(Server)
1. server_code01 2. server_code02 3. server_code03
- 12SSM整合
u 三大框架基本概念 spring.SpringMVC.Mybatis u 整合思路 u 环境准备 u 工程结构 u SPRING + SPING MVC + MYBATIS 三大框架整合 ...
- [bzoj3339]Rmq Problem||[bzoj3585]mex_线段树
Rmq Problem bzoj-3339||mex bzoj-3585 题目大意:给定一个长度为n的数列a,多次讯问区间l,r中最小的不属于集合{$A_l,A_{l+1}...A_r$}的非负整数. ...
- FFmpeg基础库编程开发学习笔记——音频常见格式及字幕格式
声明一下:这些关于ffmpeg的文章仅仅是用于记录我的学习历程和以便于以后查阅,文章中的一些文字可能是直接摘自于其它文章.书籍或者文献,学习ffmpeg相关知识是为了使用在Android上,我也才是刚 ...