zoukankan      html  css  js  c++  java
  • 使用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 }
  • 相关阅读:
    关于oracle当中数据类型转换的问题
    CASE WHEN的两种格式
    C#设置默认打印机
    运用Merge Into实现增加或更新数据
    增加或修改的存储过程
    深拷贝与浅拷贝
    sql server两种分页方法
    获取sql执行时间
    inserted触发器,一张表插入数据时,同时向另外一张表插入数据
    List<string[]> 如何去重
  • 原文地址:https://www.cnblogs.com/dalovess/p/6947368.html
Copyright © 2011-2022 走看看