关于Delegate 和 MulticastDelegate的实现
在C#中,我们使用关键字delegate来定义委托,如:
public delegate void MyDelegate(object obj, int x);
在进行编译时,以上的代码将产生一个类定义:
public class MyDelegate : System.MulticastDelegate {
public MyDelegate(Object target, IntPtr methodPtr);
public void virtual Invoke(object obj, int x); // 和委托中的参数一样.
public virtual IAsyncResult BeginInvoke(object obj, int x,
AsyncCallback callback, object o);
public virtual void EndInvoke(IAsyncResult result);
}
在以上代码中,构造函数中的参数:target 为对象实例的引用,methodPtr为用来标识回调方法。MulticastDelegate继承自Delegate,实际上Delegate类有四个私有字段:
1、private Object _target;
2、private IntPtr _methodPtr;
3、private IntPtr _methodPtrAux;
4、private RuntimeMethodInfo _method;
其中_target是调用方法的对象实例的引用,如果调用方法是static的,那么就不存在对象实例的引用,这时target为null。_methodPtr是用来标识要调用的方法。
在上面的MyDelegate委托中,MyDelegate的构造构数就是将_taget和_methodPtr进行初始化。
而 在MulticastDelegate类中,增加了一个私有字段:private MulticastDelegate _prev;这个_prev字段指向的是一个MulticastDelegate类型的引用,也就是说利用指向另一个MutlicastDelegate 类型的_prev字段来组成一个委托链表。
如果要向委托链表中增加和删除委托,C#中使用以下语法实现:
MyDelegate myDelegate = new MyDelegate(DelegateMethod1);
myDelegate += new MyDelegate(DelegateMethod2); //添加(Delegate.Combine)
myDelegate -= new MyDelegate(DelegateMethod2); // 删除(Delegate.Remove)
在 新增一个委托到委托链表时,MyDelegate类的构造函数将调用基类MulticastDelegate的构造函数,将字段_target 和 _methodPtr初始化,并将MulticastDelegate的_prev字段初始化为null.在调用Remove方法时,它也会构造一个 MyDelegate的实例,也会初始化基类的_target、_methodPtr、和_prev字段。构造完后,Remove方法会先扫描委托链表, 如发现有和新创建的委托对象相等的委托对象,则将它从链表中删除,如没有找到,则不作做任何操作。