使用GetInvocationList对委托链进行更多的控制
Posted bruce_Lin
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用GetInvocationList对委托链进行更多的控制相关的知识,希望对你有一定的参考价值。
委托链中所有项都会被调用,因为委托类型的 Invoke 方法包含了对数组中的所有项进行遍历的代码。这是一个很简单的算法。尽管这个简单的算法足以应付很多情形,但也有它的局限性。例如,除了最后一个返回值,其他所有回调方法的返回值都会被丢弃。但局限并不止于此。如果被调用的委托中有一个抛出了异常或阻塞了相当长一段时间,会出现什么情况呢?由于这个简单的算法是顺序调用链中的每一个委托,所以一个委托对象出现问题,链中后续的所有对象都调用不了啊。显然,这个算法还不够健壮性。
所以 MulticastDelegate(派生于 Delegate)类提供了一个实例方法 GetInvocationList,用于显式调用链中的每一个委托,并允许你使用需要的任何算法。
GetInvocationList 方法操作从 MulticastDelegate 派生的对象,返回包含 Delegate 引用的一个数组,其中每个引用都指向链中的一个委托对象。在内部,GetInvocationList 构造并初始化一个数组,让它的每个元素都引用链中的一个委托,然后返回对该数组的引用。如果 _invocationList 字段为null,返回的数组就只有一个元素,该元素引用链中唯一的委托,即委托实例本身。
如下代码演示:
1 using System; 2 using System.Text; 3 4 namespace _17._5._2取得对委托链调用的更多控制 5 { 6 class Program 7 { 8 // 定义委托来查询一个组件的状态 9 private delegate string GetStatus(); 10 11 static void Main(string[] args) 12 { 13 // 声明空委托链 14 GetStatus getStatus = null; 15 16 // 构造3个组件,将它们的状态方法添加到委托链中 17 getStatus += new GetStatus(new Light().SwitchPosition); 18 getStatus += new GetStatus(new Fan().Speed); 19 getStatus += new GetStatus(new Speaker().Volume); 20 21 // 显式整理好的状态报告,反映这3个组件的状态。 22 Console.WriteLine(GetComponentStatusReport(getStatus)); 23 24 Console.ReadKey(); 25 } 26 27 // 该方法查询几个组件并返回状态报告 28 private static string GetComponentStatusReport(GetStatus status) 29 { 30 // 如果委托链为空,就不进行任何操作 31 if (status == null) return null; 32 33 // 用下面的变量来创建状态报告 34 StringBuilder report = new StringBuilder(); 35 36 // 获得一个数组,其中每个元素都是链中的委托 37 Delegate[] arrayOfDelegates = status.GetInvocationList(); 38 39 // 遍历数组中每一个委托 40 foreach (GetStatus getStatus in arrayOfDelegates) 41 { 42 try 43 { 44 // 获得一个组件的状态字符串 45 report.AppendFormat("{0}{1}{1}", getStatus(), Environment.NewLine); 46 } 47 catch (InvalidOperationException e) 48 { 49 // 在状态报告中为该组件生成一个错误记录。 50 object component = getStatus.Target; 51 52 report.AppendFormat( 53 "Failed to get status from {1}{2}{0} Error: {3}{0}{0}", 54 Environment.NewLine, 55 ((component == null) ? "" : component.GetType() + "."), 56 getStatus.Method.Name, 57 e.Message); 58 } 59 } 60 61 return report.ToString(); 62 } 63 } 64 65 // 定义一个灯组件 66 internal sealed class Light 67 { 68 // 该方法返回灯的状态 69 public string SwitchPosition() 70 { 71 return "The light is off"; 72 } 73 } 74 75 // 定义一个风扇组件 76 internal sealed class Fan 77 { 78 // 该方法返回风扇组件 79 public string Speed() 80 { 81 throw new InvalidOperationException("The fan broke due to overheating"); 82 } 83 } 84 85 // 定义一个扬声器组件 86 internal sealed class Speaker 87 { 88 // 该方法返回扬声器的状态 89 public string Volume() 90 { 91 return "The volume is loud"; 92 } 93 } 94 }
以上是关于使用GetInvocationList对委托链进行更多的控制的主要内容,如果未能解决你的问题,请参考以下文章