看过上篇博文的话,具体的测试结果大家可能已心中有数。即当主题发布“毛毛雨”时,学校和公司两个主题依次收到了通知。主题发布“飓风”消息时,学校收到了通知,而公司却没有。如下图:

  本例中主题使用委托作为载体,发送消息通知。如DelegateSubject.Notify方法所示,发送新消息时调用委托实例 tempNotifyHander(Message)。可以看出委托的调用形式和调用方法一样(但形似神不似)。在这里,委托实例上注册了两个观察者的NewMessage方法,形成了委托链。在委托实例被调用时,委托链中的方法依次调用。

  结论:

  调用委托并不像调用方法一样简单,一个委托实例调用后,可以执行委托链上的多个方法;而方法仅仅是方法。

  让主题的通知更健壮:

  将委托像方法一样进行调用,这在用法上是没有问题的。但如果你的系统对健壮性有要求,需要你把握委托调用的内部细节(如保证即使“飓风”来了,学校和公司都能收到通知)。这时,要不能“像调用方法一样简单地调用委托了”。可以尝试通过Delegate.GetInvocationList方法获取委托实例上注册的委托链,然后进行自己的处理。一个简单的处理实例如下:

//通过委托发送通知(调用观察者接收消息的方法)
        public void Notify()
        {
            NotifyEventHandler tempNotifyHander = NotifyObservers;
            if (tempNotifyHander != null)
            {
                //tempNotifyHander(Message);
                //获取委托链
                Delegate[] chain = tempNotifyHander.GetInvocationList();              
                foreach (Delegate item in chain)
                {
                    try
                    {
                        item.DynamicInvoke(new object[] { Message });//依次调用委托进行通知
                    }
                    catch (Exception ex)              //某个观察者接收到消息后异常了
                    {
                        Console.WriteLine(ex.InnerException.Message);//记录异常信息
                        continue;                     //继续通知下一观察者
                    }
                }
            }
        }

  ps:对应观察者接收事件中的阻塞问题,可以使用Delegate.BeginInvoke方法进行处理。