使用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 ...
 
随机推荐
- div+css  组织结构
			
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>家谱 ...
 - MySQL详细操作
			
一.用户管理 -- 创建用户 create user "用户名"@"IP地址" identified by "密码"; "; &q ...
 - opcache的配置
			
; Enable Zend OPcache extension module zend_extension=opcache.so ; Determines if Zend OPCache is ena ...
 - C# WPF 窗体传递消息
			
对于存在窗体的WPF程序(或者说,起码在任务栏上有个图标,即ShowInTaskbar = true),互相传递消息是很容易的. 步骤: 1,寻找窗体的句柄 2,运用windows API: Send ...
 - BZOJ1191 超级英雄Hero (匈牙利算法)
			
直接跑匈牙利,注意到“只有当选手正确回答一道题后,才能进入下一题,否则就被淘汰”,一旦无法满足就直接退出. #include <cstdio> #include <algorithm ...
 - Swift: 一句话获取虚拟机上APP所在的目录
			
在XCode6上,虚拟机的App的存放位置发生了变化,通过下面语句,我们可以立即获得其所在的位置: println(NSTemporaryDirectory())
 - ioctl在socket中的一些用法及示例
			
原文: http://blog.chinaunix.net/uid-20692625-id-3172833.html ----------------------------------------- ...
 - UVa 642 - Word Amalgamation
			
题目:给你一个单词列表.再给你一些新的单词.输出列表中又一次排列能得到此新单词的词. 分析:字符串.对每一个字符串的字母排序生成新的传f(str).总体排序,用二分来查找就可以. 说明:注意输出要满足 ...
 - 自定义列标题 case  when
			
set@schoolid=41;select l.StartTime,l.EndTime,c.EntranceYear as 入学级,cg.Grade as 年级,c.ClassName as 班级名 ...
 - postgresql数据库psql控制台操作命令
			
登录postgresql数据库控制台 psql 数据库名 登录成功显示 [zpf@kevin ~]$ psql postgres psql (9.4.1) Type "help" ...