前面我们已经知道链式委托的基本特性就是一个以委托组成的链表,而当委托链上任何一个委托方法被调用时,其后面的所有委托方法都将会被依次地顺序调用。那么问题来了,委托链上的顺序是如何形成的?这里回顾一下上面1.3中的示例代码,通过Reflector反编译一下,一探究竟:.
从编译后的结果可以看到,+=的本质又是调用了Delegate.Combine方法,该方法将两个委托链接起来,并且把第一个委托放在第二个委托之前,因此可以将两个委托的相加理解为Deletegate.Combine(Delegate a,Delegate b)的调用。我们可以再次回顾System.MulticastDelegate的类结构:
其中_prev成员是一个指向下一个委托成员的指针,当某个委托被链接到当前委托的后面时,该成员会被设置为指向那个后续的委托实例。.NET也是依靠这一个引用来逐一找到当前委托的所有后续委托并以此执行方法。
那么,问题又来了?程序员是否能够有能力控制链式委托的执行顺序呢?也许我们会说,只要在定义时按照需求希望的顺序来依次添加就可以了。但是,如果要在定义完成之后突然希望改变执行顺序呢?又或者,程序需要按照实际的运行情况再来决定链式委托的执行顺序呢?
接下来就是见证奇迹的时刻:
// 申明委托并绑定第一个方法
TestMulticastDelegate tmd = new TestMulticastDelegate(PrintMessage1);
// 绑定第二个方法
tmd += new TestMulticastDelegate(PrintMessage2);
// 绑定第三个方法
tmd += new TestMulticastDelegate(PrintMessage3);
// 获取所有委托方法
Delegate[] dels = tmd.GetInvocationList();
上述代码调用了定义在 System.MulticastDelegate 中的 GetInvocationList() 方法,用以获得整个链式委托中的所有委托。接下来,我们就可以按照我们所希望的顺序去执行它们。