委托链中所有项都会被调用,因为委托类型的 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对委托链进行更多的控制的更多相关文章

  1. 链方法[C# 基础知识系列]专题三:如何用委托包装多个方法——委托链

    最近研究链方法,稍微总结一下,以后继续补充: 弁言: 上一专题分析了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的分析都是委托只是封装一个方法,那委 ...

  2. [C# 基础知识系列]专题三:如何用委托包装多个方法——委托链 (转载)

    引言: 上一专题介绍了下编译器是如何来翻译委托的,从中间语言的角度去看委托,希望可以帮助大家进一步的理解委托,然而之前的介绍都是委托只是封装一个方法,那委托能不能封装多个方法呢?因为生活中经常会听到, ...

  3. .net委托链

    委托链可以增加方法,可以移除方法,如果是无返回值的方法,我们把它们都绑定到一个委托上面的话,直接调用,那么调用此委托就会依次调用其中的方法:但是如果是多个有返回值的委托链,如果我们不采用特殊手段,直接 ...

  4. 委托、Lambda表达式、事件系列04,委托链是怎样形成的, 多播委托, 调用委托链方法,委托链异常处理

    委托是多播委托,我们可以通过"+="把多个方法赋给委托变量,这样就形成了一个委托链.本篇的话题包括:委托链是怎样形成的,如何调用委托链方法,以及委托链异常处理. □ 调用返回类型为 ...

  5. C#.NET常见问题(FAQ)-delegate委托链如何使用

    委托链本质就是你把一堆要执行的东西放到一个list里面,当要触发一组事情的时候,就不需要一个一个写一遍了(比如厂里食堂开饭了,这个方法一执行,要让厨师A时间在食堂等候打饭,B类员工在某个时间排队打饭, ...

  6. 委托Delegate,多播委托和委托链

    定义一个委托 public delegate void CalculateDelegate(int 32 x,int 32 y); 定义一个委托类型的变量 public static Calculat ...

  7. JavaScript和JQuery中的事件\委托链\事件冒泡\事件捕获,兼容所有浏览器

    有做过北大青鸟培训讲师经验的我,如今在一家公司做技术部经理的职位,发现有很多程序员的基本功相当糟糕,在组织企业内部培训时讲解了一些案例,总结了一些经典代码,希望对自己和有需要的人提供一些帮助吧: Ja ...

  8. C# 委托之把委托从委托链(多播委托)移除

    运用“-”运算符将委托从委托链移除 class HelloWorld { //定义委托类型 delegate void DelegationChain(); static void Main(stri ...

  9. C# 委托链、多路广播委托

    委托链.多路广播委托:也就是把多个委托链接在一起,我们把链接了多个方法的委托称为委托链或多路广播委托 例: class HelloWorld { //定义委托类型 delegate void Dele ...

随机推荐

  1. ASP.NET Log4Net日志的配置及使用,文件写入

    Log4net是Apache log4j框架在Microsort.NET平台实现的框架. 帮助程序员将日志信息输出到各种目标(控制台,数据库,文件等) 1.新建一个ASP.NET项目 2.新建一个 l ...

  2. openstack——horizon篇

    一.horizon 介绍:       理解 horizon   Horizon 为 Openstack 提供一个 WEB 前端的管理界面 (UI 服务 )通过 Horizone 所提供的 DashB ...

  3. MySQL多表连接操作

    select * from userinfo ,dapartment where userinfo.part_id = dapartment.id; --左连接: 左边全部显示 select * fr ...

  4. python文件头的含义

    一.指定解释器及其路径 在Linux\Mac上,可以用./文件路径直接运行.py文件 这时,需要在python文件开头指定解释器及其路径 #!/usr/bin/python 这样系统就直接按pytho ...

  5. Python模块 os.walk

    Os.walk os.walk(top,topdown=True,onerror=None,followlinks=False) os.walk()是python中内置(built-in)的目录树生成 ...

  6. BZOJ 2038 2009国家集训队 小Z的袜子【模板·莫队】

    [题解] 1,先说说莫队算法. 莫队算法是用来离线处理区间问题的算法.非常易于理解和使用,且运用十分广泛. 假设我们现在已知区间[L,R]的答案,如果我们能以较低的时间复杂度扩展得到区间$[L-1,R ...

  7. hdu2001 计算两点间的距离【C++】

    计算两点间的距离 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Su ...

  8. ubuntu添加开机自启和sysv-rc-conf

    此文ubuntu使用sysvinit,而非upstart UBUNTU添加开机自动启动程序方法 1. 开机启动时自动运行程序    Linux加载后, 它将初始化硬件和设备驱动, 然后运行第一个进程i ...

  9. springCloud学习-分布式配置中心(Spring Cloud Config)

    1.简介 Spring Cloud Config :分布式配置中心,方便服务配置文件统一管理,它支持配置服务放在配置服务的内存中(即本地),也支持放在远程Git仓库中.在spring cloud co ...

  10. Android LaunchAnyWhere (Google Bug 7699048)漏洞具体解释及防御措施

    開始 近日,Google修复一个组件安全的漏洞LaunchAnyWhere(Google Bug 7699048). 这个漏洞属于Intend Based提取漏洞,攻击者利用这个漏洞,能够突破了应用间 ...