使用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 ...
随机推荐
- CentOS6.9下NFS配置说明(转载)
NFS是Network File System的缩写,即网络文件系统.它的主要功能是通过网络(一般是局域网)让不同的主机系统之间可以共享文件或目录.NFS客户端可以通过挂载(mount)的方式将NFS ...
- CodeForces 580B(尺取法)
Kefa and Company 题意:Kefa这个人要去吃饭,他要邀请一些朋友一起去,他的每个朋友有两个属性金钱和关系度,要求邀请的人里边任意两个人之间的金钱差的绝对值不大于d:求被邀请的所有朋友的 ...
- 搭建 Seafile 专属网盘
准备域名 任务时间:15min ~ 20min 域名注册 如果您还没有域名,可以在腾讯云上选购,过程可以参考下面的视频. 视频 - 在腾讯云上购买域名 域名解析 域名购买完成后, 需要将域名解析到实验 ...
- 超经典SQL练习题,做完这些你的SQL就过关了
使用方法:我用的数据库是 Ms SQL Server 2008 ,练习时应当自己建数据,自己先思考,切勿急躁翻答案!否则效果减半,做完这些,恭喜你,你的 SQL 就算过关了. 测试表格 --1.学生表 ...
- [POJ2104] 区间第k大数 [区间第k大数,可持久化线段树模板题]
可持久化线段树模板题. #include <iostream> #include <algorithm> #include <cstdio> #include &l ...
- Grails里的集成测试代码试例
测试的命令,3和2不一样了,要找找.. User.groovy package com.grailsinaction class User { String loginId String passwo ...
- 在Centos安装oracle_11gR2进度68%"Error in invoking target mkldflags ntcontab.o nnfgt.o of makefile..”
http://www.xwood.net/_site_domain_/_root/5870/5874/t_c265367.html
- 1393 0和1相等串 51nod
1393 0和1相等串 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 给定一个0-1串,请找到一个尽可能长的子串,其中包含的0与1的个数相等. I ...
- Findbug插件静态java代码扫描工具使用
本文转自http://blog.csdn.net/gaofuqi/article/details/22679609 感谢作者 FindBugs 是由马里兰大学提供的一款开源 Java静态代码分析工具. ...
- ubuntu设置不睡眠的方法
Ubuntu系统不睡眠设置方法:要完成这个设置Ubuntu有两种方法:第一种是打开 System Settings –> Power,中文版是打开系统设置 -> 电源),然后进行设置.但不 ...