技术开发 频道

.NET面面观——探索.Net中的委托

  在上面的!do命令的输出中,我们看到了MethodTable:00263100,这就是该对象的方法表地址(关于方法表更详细的讨论会在后面的章节介绍到,现在你只要把他看做一个记录对象所有方法的列表就行了,该列表里每一个条目就是一个方法)。现在我们要看看Yuyijq.DotNet.Chapter2.TestDelegate..Test方法的内存地址,看其是否与_methodPtr的值是一致的,那么首先就要获得Yuyijq.DotNet.Chapter2.TestDelegate.的实例中MethodTable的值:

  !do 019928a4

  Name: Yuyijq.DotNet.Chapter2.TestDelegate

  MethodTable: 00263048

  EEClass: 002612f8

  Size: 12(0xc) bytes

  (E:\Study\Demo\Demo\bin\Debug\Demo.exe)

  Fields:

  None

  现在知道了其方法表的值为00263048,然后使用下面的命令找到Yuyijq.DotNet.Chapter2.TestDelegate..Test方法的地址:

  !dumpmt -md 00263048

  EEClass: 002612f8

  Module: 00262c5c

  Name: Yuyijq.DotNet.Chapter2.TestDelegate

  mdToken: 02000003 (E:\Study\Demo\Demo\bin\Debug\Demo.exe)

  BaseSize: 0xc

  ComponentSize: 0x0

  Number of IFaces in IFaceMap: 0

  Slots in VTable: 9

  --------------------------------------

  MethodDesc Table

  Entry MethodDesc JIT Name

  .......

  0026c010 00262ffc NONE Yuyijq.DotNet.Chapter2.TestDelegate.AssignDelegate()

  0026c018 0026300c NONE Yuyijq.DotNet.Chapter2.TestDelegate.Test(Int32)

  ......

  Entry这一列就是一个JIT Stub。看看,果然与_methodPtr的是一致的,因为这时Test方法还没有经过JIT(JIT列为NONE),所以_methodPtr指向的是这里的JIT Stub。

  如果给委托绑定一个静态方法呢?现在我们把Test方法改为静态的,那实例化委托的时候,就不能用this.Test了,而应该用TestDelegate.Test。还是在原位置设置断点,使用与上面相同的命令,查看_target与_methodPtr的值。

  MT Field Offset Type VT Attr Value Name

  704b84dc 40000ff 4 System.Object 0 instance 01e928b0 _target

  704bb188 4000101 c System.IntPtr 1 instance 007809C4 _methodPtr

  704bb188 4000102 10 System.IntPtr 1 instance 0025C018 _methodPtrAux

  你会发现这里的_target字段的值就是MyDelegate的实例myDelegate的地址。然后我们通过上面的方法,找到Test方法的地址,发现_methodPtrAux的值与该值是相同的。

0
相关文章