姚明为什么要退役,为什么要MEF

简介

本文章想通过一个案例说说MEF用来解决什么问题,这将有助于您更有效的使用MEF.

背景

通常,创建可重用的代码库并在程序中使用。在传统的Win32应用程序中,如果一个类库被引用至某个应用程序,连接器(Linker)在PE Header中添加此类库的引用。当运行时试图加载应用程序,加载器(Loader)将执行如下操作:
  1. 找出所有依赖项;
  2. 加载它们到内存;
  3. 映射它们到相应的指针;
  4. 启动主例程.
但在.NET环境中,中间有CLR和JIT机制,所以情况有些许不同.加载器只会加载Main方法中使用的那些类库,IL(Intermediate Language,中间语言)将Main方法中调用的其它方法在需要时即时编译(JIT)并加载到内存,这也是MEF的基础之一.
这是官方对MEF的定义:
The Managed Extensibility Framework (MEF) is a new library in .NET that enables greater reuse of applications and components. Using MEF, .NET applications can make the shift from being statically compiled to dynamically composed. If you are building extensible applications, extensible frameworks and application extensions, then MEF is for you.

案例

下来看一个明显感觉到需要用到MEF的场景,创建一个控制台应用程序来达到此目的。
  1. 创建一个简单的控制台应用程序 “WOMEF”(Without MEF);
  2. 用如下代码替换Program.cs;
using System; using WOMEFLib; namespace WOMEF { class Program { static void Main(string[] args) { Console.WriteLine("按X键退出,否则继续."); ConsoleKeyInfo key = Console.ReadKey(true); while (key.Key != ConsoleKey.X) { new Program().Speak(); key = Console.ReadKey(true); } } public void Speak() { Console.Write("Speak:"); ISpeak s = new Speak(); s.SayHello(); } } }
在新的类库项目中定义ISpeakSpeak:
  1. 在解决方案中添加类库项目 “WOMEFLib”;
  2. 删除Class1.cs;
  3. 添加接口ISpeak.cs; namespace WOMEFLib { public interface ISpeak { void SayHello(); } }
  4. 添加接口的实现Speak.cs; using System; namespace WOMEFLib { public class Speak:ISpeak { public void SayHello() { Console.WriteLine("Hello World!"); } } }
在WOMEF项目中添加对WOMEFLib项目的引用,解决方案中右键WOMEF项目,属性\生成\配置,选择”Release”,保存、生成、调试,这都不是我们关注的重点,我们要关注的是这两个程序集的相关的问题。
为什么要MEF姚明为什么要退役
[图-1 设置Release]
我们将要验证以下几点:
  1. 加载器何时加载WOMEFLib.dll;
  2. 当应用程序启动时缺少WOMEFLib.dll时会怎样;
  3. Program.Speak方法何时被JIT编译;
  4. 第一次等待用户输入时将WOMEFLib.dll复制到程序所在目录会如何;
要验证以上几点,我们需要在运行时查看方法列表及程序集信息,以下将围绕这几点进行阐述。
需要用到的工具,Windbg,MSIL 反汇编程序,关于这两个工具可从 这里下载安装 。
有关SOS 调试扩展的资料可参考这里。

加载器何时加载WOMEFLib.dll

  1. 启动Windbg;
  2. 单击 File->Open executable,选择Release目录下WOMEF.exe,打开; 为什么要MEF姚明为什么要退役
    [图-2 Windbg 打开WOMEF.exe]
  3. Windbg 会停在断点int3处(WinDbg 会在调试目标的进程中创建一个远线程,并在这个远线程中执行 ntdll!DbgBreakPoint 函数,它会在目标进程中产生一次 int3 异常,这个异常被Windbg捕获,所以WOMEF.exe就中断到调试器中了),按F5继续; Microsoft (R) Windows Debugger Version 6.12.0002.633 X86 Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Symbol search path is: *** Invalid *** **************************************************************************** * Symbol loading may be unreliable without a symbol search path. * * Use .symfix to have the debugger choose a symbol path. * * After setting your symbol path, use .reload to refresh symbol locations. * **************************************************************************** Executable search path is: ModLoad: 01330000 01338000 WOMEF.exe ModLoad: 77570000 776ad000 ntdll.dll ModLoad: 71aa0000 71aea000 C:\Windows\SYSTEM32\MSCOREE.DLL ModLoad: 760c0000 76194000 C:\Windows\system32\KERNEL32.dll ModLoad: 75830000 7587a000 C:\Windows\system32\KERNELBASE.dll (1228.26bc): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=001af66c edx=775b6344 esi=fffffffe edi=00000000 eip=7760ebbe esp=001af688 ebp=001af6b4 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 *** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ntdll!LdrVerifyImageMatchesChecksum+0x633: 7760ebbe cc int 3 0:000> g ModLoad: 75eb0000 75f50000 C:\Windows\system32\ADVAPI32.dll ModLoad: 75e00000 75eac000 C:\Windows\system32\msvcrt.dll ModLoad: 76010000 76029000 C:\Windows\SYSTEM32\sechost.dll ModLoad: 75d50000 75df1000 C:\Windows\system32\RPCRT4.dll ModLoad: 71a30000 71a96000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll ModLoad: 761a0000 761f7000 C:\Windows\system32\SHLWAPI.dll ModLoad: 77750000 7779e000 C:\Windows\system32\GDI32.dll ModLoad: 75c80000 75d49000 C:\Windows\system32\USER32.dll ModLoad: 776b0000 776ba000 C:\Windows\system32\LPK.dll ModLoad: 774d0000 7756d000 C:\Windows\system32\USP10.dll ModLoad: 75fe0000 75fff000 C:\Windows\system32\IMM32.DLL ModLoad: 773b0000 7747c000 C:\Windows\system32\MSCTF.dll ModLoad: 6d910000 6df80000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll ModLoad: 6d7a0000 6d85e000 C:\Windows\system32\MSVCR100_CLR0400.dll (1228.26bc): Unknown exception - code 04242420 (first chance) ModLoad: 6c7d0000 6d591000 C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\b58db50e1b6b9a69014a31d72b611c30\mscorlib.ni.dll ModLoad: 6c5e0000 6c5f0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dll ModLoad: 76400000 7655c000 C:\Windows\system32\ole32.dll ModLoad: 75640000 7564c000 C:\Windows\system32\CRYPTBASE.dll ModLoad: 63b80000 63be0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll ModLoad: 003a0000 003a8000 WOMEFLib.dll ModLoad: 004d0000 004d8000 WOMEFLib.dll
  4. 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
  5. 在Windbg窗体中,单击菜单 Debug->Break(或者按Ctrl+Break), (1228.2524): Break instruction exception - code 80000003 (first chance) eax=7ffda000 ebx=00000000 ecx=00000000 edx=7760d7eb esi=00000000 edi=00000000 eip=775a3370 esp=012ffcd0 ebp=012ffcfc iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 775a3370 cc int 3
  6. 加载CLR,在Windbg命令行中输入”.loadby sos clr” 注意,由于在.NET FW 4中CLR 的dll文件更名为clr.dll,所以在.NET4中应输入”.loadby sos clr”,在.NET FW3中应输入”.loadby sos.dll mscorwks” 0:004> .loadby sos clr
  7. 在Windbg命令行中输入”!dumpdomain”命令列出进程中的所有程序集; 0:004> !dumpdomain ********************************************************************* * Symbols can not be loaded because symbol path is not initialized. * * * * The Symbol Path can be set by: * * using the _NT_SYMBOL_PATH environment variable. * * using the -y argument when starting the debugger. * * using .sympath and .sympath+ * ********************************************************************* PDB symbol for clr.dll not loaded -------------------------------------- System Domain: 6df03478 LowFrequencyHeap: 6df03784 HighFrequencyHeap: 6df037d0 StubHeap: 6df0381c Stage: OPEN Name: None -------------------------------------- Shared Domain: 6df03140 LowFrequencyHeap: 6df03784 HighFrequencyHeap: 6df037d0 StubHeap: 6df0381c Stage: OPEN Name: None Assembly: 002462e8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 00246388 Module Name 6c7d1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll -------------------------------------- Domain 1: 00201520 LowFrequencyHeap: 0020189c HighFrequencyHeap: 002018e8 StubHeap: 00201934 Stage: OPEN SecurityDescriptor: 00202c98 Name: WOMEF.exe Assembly: 002462e8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 00246388 SecurityDescriptor: 002460b8 Module Name 6c7d1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Assembly: 00253588 [D:\Test\Test\WOMEF\bin\Release\WOMEF.exe] ClassLoader: 00253628 SecurityDescriptor: 00252dd8 Module Name 001d2e9c D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Assembly: 00262830 [D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll] ClassLoader: 002628d0 SecurityDescriptor: 00255df8 Module Name 001d38d0 D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll
  8. 在应用程序域中有三个程序集被加载,分别是mscorlib.dll、WOMEF.exe、WOMEFLib.dll,见粗体字部分;
  9. 可见加载器加载了引用的程序集WOMEFLib.dll,虽然还没有使用此dll中的任何类型,此刻执行到 ConsoleKeyInfo key = Console.ReadKey(true);
    虽然还没有使用WOMEFLib.dll中的任何东西,但依然被加载,这是为什么呢?因为WOMEFLib.dll已经在WOMEF.exe的manifest中,请先关闭Windbg。
  10. 启动IL,打开WOMMEF.exe; 为什么要MEF姚明为什么要退役为什么要MEF姚明为什么要退役
  11. 双击 manifest,可以看到如下 为什么要MEF姚明为什么要退役

当应用程序启动时缺少WOMEFLib.dll时会怎样

接下来我们测试下当缺少WOMEFLib.dll时会发生什么,将Release目录中的WOMEFLib.dll剪贴到别的地方,如桌面,
  1. 启动Windbg,File-> Open executable,打开Release目录下的WOMEF.exe,按F5继续; CommandLine: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Symbol search path is: *** Invalid *** **************************************************************************** * Symbol loading may be unreliable without a symbol search path. * * Use .symfix to have the debugger choose a symbol path. * * After setting your symbol path, use .reload to refresh symbol locations. * **************************************************************************** Executable search path is: ModLoad: 000e0000 000e8000 WOMEF.exe ModLoad: 77570000 776ad000 ntdll.dll ModLoad: 71aa0000 71aea000 C:\Windows\SYSTEM32\MSCOREE.DLL ModLoad: 760c0000 76194000 C:\Windows\system32\KERNEL32.dll ModLoad: 75830000 7587a000 C:\Windows\system32\KERNELBASE.dll (2744.ab8): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=002ff8a4 edx=775b6344 esi=fffffffe edi=00000000 eip=7760ebbe esp=002ff8c0 ebp=002ff8ec iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 *** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ntdll!LdrVerifyImageMatchesChecksum+0x633: 7760ebbe cc int 3 0:000> g ModLoad: 75eb0000 75f50000 C:\Windows\system32\ADVAPI32.dll ModLoad: 75e00000 75eac000 C:\Windows\system32\msvcrt.dll ModLoad: 76010000 76029000 C:\Windows\SYSTEM32\sechost.dll ModLoad: 75d50000 75df1000 C:\Windows\system32\RPCRT4.dll ModLoad: 71a30000 71a96000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll ModLoad: 761a0000 761f7000 C:\Windows\system32\SHLWAPI.dll ModLoad: 77750000 7779e000 C:\Windows\system32\GDI32.dll ModLoad: 75c80000 75d49000 C:\Windows\system32\USER32.dll ModLoad: 776b0000 776ba000 C:\Windows\system32\LPK.dll ModLoad: 774d0000 7756d000 C:\Windows\system32\USP10.dll ModLoad: 75fe0000 75fff000 C:\Windows\system32\IMM32.DLL ModLoad: 773b0000 7747c000 C:\Windows\system32\MSCTF.dll ModLoad: 6d910000 6df80000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll ModLoad: 6d7a0000 6d85e000 C:\Windows\system32\MSVCR100_CLR0400.dll (2744.ab8): Unknown exception - code 04242420 (first chance) ModLoad: 6c7d0000 6d591000 C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\b58db50e1b6b9a69014a31d72b611c30\mscorlib.ni.dll ModLoad: 6c5e0000 6c5f0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dll ModLoad: 76400000 7655c000 C:\Windows\system32\ole32.dll ModLoad: 75640000 7564c000 C:\Windows\system32\CRYPTBASE.dll ModLoad: 63b80000 63be0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll (2744.ab8): C++ EH exception - code e06d7363 (first chance) (2744.ab8): C++ EH exception - code e06d7363 (first chance) (2744.ab8): C++ EH exception - code e06d7363 (first chance) (2744.ab8): CLR exception - code e0434352 (first chance)
  2. 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
  3. 虽然依赖的程序集WOMEFLib.dll已经没有了,程序依然能够正常运行到此处,这点比较有趣,为什么加载器没有报”找不到WOMEFLib.dll”的错误呢?答案是Program.Speak()还没有被JIT编译,我们接下来将验证这一点,请先关闭Windbg。
 

Program.Speak方法何时被JIT编译

我们来验证下Program.Speak方法何时被JIT编译,将刚才移动到桌面的WOMEFLib.dll文件再次移动回到Release目录来
  1. 启动Windbg,File-> Open executable,打开Release目录下的WOMEF.exe,按F5继续;
  2. 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
  3. 在Windbg窗体中,单击菜单 Debug->Break(或者按Ctrl+Break);
  4. 加载CLR,在Windbg命令行中输入”.loadby sos clr”;
  5. 在Windbg命令行中输入”!dumpdomain”命令列出进程中的所有程序集; CommandLine: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Symbol search path is: *** Invalid *** **************************************************************************** * Symbol loading may be unreliable without a symbol search path. * * Use .symfix to have the debugger choose a symbol path. * * After setting your symbol path, use .reload to refresh symbol locations. * **************************************************************************** Executable search path is: ModLoad: 00b20000 00b28000 WOMEF.exe ModLoad: 77570000 776ad000 ntdll.dll ModLoad: 71aa0000 71aea000 C:\Windows\SYSTEM32\MSCOREE.DLL ModLoad: 760c0000 76194000 C:\Windows\system32\KERNEL32.dll ModLoad: 75830000 7587a000 C:\Windows\system32\KERNELBASE.dll (1228.1374): Break instruction exception - code 80000003 (first chance) eax=00000000 ebx=00000000 ecx=0028f9b0 edx=775b6344 esi=fffffffe edi=00000000 eip=7760ebbe esp=0028f9cc ebp=0028f9f8 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 *** ERROR: Symbol file could not be found. Defaulted to export symbols for ntdll.dll - ntdll!LdrVerifyImageMatchesChecksum+0x633: 7760ebbe cc int 3 0:000> g ModLoad: 75eb0000 75f50000 C:\Windows\system32\ADVAPI32.dll ModLoad: 75e00000 75eac000 C:\Windows\system32\msvcrt.dll ModLoad: 76010000 76029000 C:\Windows\SYSTEM32\sechost.dll ModLoad: 75d50000 75df1000 C:\Windows\system32\RPCRT4.dll ModLoad: 71a30000 71a96000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll ModLoad: 761a0000 761f7000 C:\Windows\system32\SHLWAPI.dll ModLoad: 77750000 7779e000 C:\Windows\system32\GDI32.dll ModLoad: 75c80000 75d49000 C:\Windows\system32\USER32.dll ModLoad: 776b0000 776ba000 C:\Windows\system32\LPK.dll ModLoad: 774d0000 7756d000 C:\Windows\system32\USP10.dll ModLoad: 75fe0000 75fff000 C:\Windows\system32\IMM32.DLL ModLoad: 773b0000 7747c000 C:\Windows\system32\MSCTF.dll ModLoad: 6d910000 6df80000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dll ModLoad: 6d7a0000 6d85e000 C:\Windows\system32\MSVCR100_CLR0400.dll (1228.1374): Unknown exception - code 04242420 (first chance) ModLoad: 6c7d0000 6d591000 C:\Windows\assembly\NativeImages_v4.0.30319_32\mscorlib\b58db50e1b6b9a69014a31d72b611c30\mscorlib.ni.dll ModLoad: 6c5e0000 6c5f0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dll ModLoad: 76400000 7655c000 C:\Windows\system32\ole32.dll ModLoad: 75640000 7564c000 C:\Windows\system32\CRYPTBASE.dll ModLoad: 63b80000 63be0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dll ModLoad: 73ae0000 73ae8000 WOMEFLib.dll ModLoad: 002b0000 002b8000 WOMEFLib.dll (1228.22b8): Break instruction exception - code 80000003 (first chance) eax=7ffda000 ebx=00000000 ecx=00000000 edx=7760d7eb esi=00000000 edi=00000000 eip=775a3370 esp=0418fb64 ebp=0418fb90 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 ntdll!DbgBreakPoint: 775a3370 cc int 3 0:004> .loadby sos clr 0:004> !dumpdomain ********************************************************************* * Symbols can not be loaded because symbol path is not initialized. * * * * The Symbol Path can be set by: * * using the _NT_SYMBOL_PATH environment variable. * * using the -y argument when starting the debugger. * * using .sympath and .sympath+ * ********************************************************************* PDB symbol for clr.dll not loaded -------------------------------------- System Domain: 6df03478 LowFrequencyHeap: 6df03784 HighFrequencyHeap: 6df037d0 StubHeap: 6df0381c Stage: OPEN Name: None -------------------------------------- Shared Domain: 6df03140 LowFrequencyHeap: 6df03784 HighFrequencyHeap: 6df037d0 StubHeap: 6df0381c Stage: OPEN Name: None Assembly: 00336478 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 00336518 Module Name 6c7d1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll -------------------------------------- Domain 1: 002f1520 LowFrequencyHeap: 002f189c HighFrequencyHeap: 002f18e8 StubHeap: 002f1934 Stage: OPEN SecurityDescriptor: 002f2c98 Name: WOMEF.exe Assembly: 00336478 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll] ClassLoader: 00336518 SecurityDescriptor: 003361a0 Module Name 6c7d1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll Assembly: 00343588 [D:\Test\Test\WOMEF\bin\Release\WOMEF.exe] ClassLoader: 00343628 SecurityDescriptor: 00342dd8 Module Name 00142e9c D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Assembly: 00352850 [D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll] ClassLoader: 003528f0 SecurityDescriptor: 00345df8 Module Name 001438d0 D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll
  6. 此刻,程序运行至Main方法的第2行,来看看WOMEF.exe的信息,在Windbg命令行中输入”!dumpmodule -mt 00142e9c”,00142e9c是WOMEF.exe的地址,如上的红色字体处; 0:004> !dumpmodule -mt 00142e9c Name: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Attributes: PEFile Assembly: 00343588 LoaderHeap: 00000000 TypeDefToMethodTableMap: 001400c4 TypeRefToMethodTableMap: 001400d0 MethodDefToDescMap: 00140130 FieldDefToDescMap: 00140140 MemberRefToDescMap: 00140144 FileReferencesMap: 001401a8 AssemblyReferencesMap: 001401ac MetaData start address: 00b220b8 (1780 bytes) Types defined in this module MT TypeDef Name ------------------------------------------------------------------------------ 00143810 0x02000002 WOMEF.Program Types referenced in this module MT TypeRef Name ------------------------------------------------------------------------------ 6caef568 0x01000001 System.Object 6caf7574 0x01000013 System.Console 6cad1fe8 0x01000014 System.ConsoleKeyInfo 00143dcc 0x01000017 WOMEFLib.ISpeak
  7. 再来看看方法表的信息,在Windbg命令行中输入”!dumpmt -md 00143810”,00143810是WOMEF.Program的地址,如上的红色字体处; 0:004> !dumpmt -md 00143810 EEClass: 00141424 Module: 00142e9c Name: WOMEF.Program mdToken: 02000002 File: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe BaseSize: 0xc ComponentSize: 0x0 Slots in VTable: 7 Number of IFaces in IFaceMap: 0 -------------------------------------- MethodDesc Table Entry MethodDesc JIT Name 6c9fa7e0 6c7d4934 PreJIT System.Object.ToString() 6c9fe2e0 6c7d493c PreJIT System.Object.Equals(System.Object) 6c9fe1f0 6c7d495c PreJIT System.Object.GetHashCode() 6ca81600 6c7d4970 PreJIT System.Object.Finalize() 0014c019 00143808 NONE WOMEF.Program..ctor() 002d0070 001437f0 JIT WOMEF.Program.Main(System.String[]) 0014c015 001437fc NONE WOMEF.Program.Speak()
  8. 可见,方法”WOMEF.Program.Speak()”的JIT状态为NONE,这意味这这个方法还没有被JIT编译,在Windbg中按F5继续运行,在控制台窗体程序中输入任意非’X’字符,CLR编译Program.Speak方法,加载WOMEFLib.dll中的Speak方法;
  9. 再次在Windbg中单击菜单 Debug->Break(或者按Ctrl+Break);
  10. 接着看看方法表信息,在Windbg命令行中输入”!dumpmt -md 00143810”,00143810是WOMEF.Program的地址,如上的红色字体处; 0:004> !dumpmt -md 00143810 EEClass: 00141424 Module: 00142e9c Name: WOMEF.Program mdToken: 02000002 File: D:\Test\Test\WOMEF\bin\Release\WOMEF.exe BaseSize: 0xc ComponentSize: 0x0 Slots in VTable: 7 Number of IFaces in IFaceMap: 0 -------------------------------------- MethodDesc Table Entry MethodDesc JIT Name 6c9fa7e0 6c7d4934 PreJIT System.Object.ToString() 6c9fe2e0 6c7d493c PreJIT System.Object.Equals(System.Object) 6c9fe1f0 6c7d495c PreJIT System.Object.GetHashCode() 6ca81600 6c7d4970 PreJIT System.Object.Finalize() 0014c019 00143808 NONE WOMEF.Program..ctor() 002d0070 001437f0 JIT WOMEF.Program.Main(System.String[]) 002d00f0 001437fc JIT WOMEF.Program.Speak()
  11. 如上,可看到WOMEF.Program.Speak的JIT状态为JIT,需要注意的一点是,若在第8步处按了X键,则WOMEF.Program.Speak不会被JIT编译。因此,当程序走到while循环体内,CLR即时编译并调用方法。
  12. 接下来我们来看看另外一种情景,当控制台程序运行到while循环体之前时,将WOMEFLib.dll复制到Release目录时会是什么状况,先关闭Windbg.
 

第一次等待用户输入时将WOMEFLib.dll复制到程序所在目录会如何

将Release目录中的WOMEFLib.dll剪贴到别的地方,如桌面
  1. 启动Windbg,File-> Open executable,打开Release目录下的WOMEF.exe,按F5继续;
  2. 此时,程序等待用户输入,显示为"按X键退出,否则继续." ,此时将WOMEFLib.dll移动回Release目录中;
  3. 输入任意非’X’字符,此时将会报错,如下:
  4. 这意味着,一旦程序启动,加载器将不会自动重新加载;为什么要MEF姚明为什么要退役
  5. 这就是MEF要解决的问题。

    以前的解决方案

    以上这些只是想让您更加清楚MEF要解决的问题,在开始用MEF之前,先看看如何用现有的技术来解决。在CLR2.0中我们可以在运行时加载程序集,加载后,我们可以创建程序集中定义的某类型的实例,比较简单,如下
    在WOMEF项目中移除对WOMEFLib项目的引用,将Program.cs替换为如下代码
    using System; using System.Reflection; namespace WOMEF { class Program { static void Main(string[] args) { Console.WriteLine("按X键退出,否则继续."); ConsoleKeyInfo key = Console.ReadKey(true); while (key.Key != ConsoleKey.X) { new Program().Speak(); key = Console.ReadKey(true); } } public void Speak() { Console.Write("Speak:"); InvokeMethod("WOMEFLib", "Speak", "SayHello"); } public object InvokeMethod(string assemblyName, string className, string methodName) { object returnObject = null; try { Type type = System.Reflection.Assembly.LoadFrom(assemblyName + ".dll").GetType(assemblyName + "." + className); MethodInfo mi = type.GetMethod(methodName); ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes); object objectinstance = ci.Invoke(null); //Invoke returnObject = mi.Invoke(objectinstance, null); } catch (TargetException tex) { throw tex; } return returnObject; } } }
     
    Invoke方法运行时加载WOMEFLib.dll,构造Speak实例,调用SayHello方法。
    先到这,明天出个差。
     
    参考:
    1. http://archive.msdn.microsoft.com/mef
    2. http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx
    3. http://msdn.microsoft.com/zh-cn/library/bb190764%28v=VS.90%29.aspx
    4. http://www.codeproject.com/KB/library/mefpart1.aspx
    5. http://stackoverflow.com/questions/4373683/unable-to-load-sos-in-windbg
    6. http://msdn.microsoft.com/zh-cn/library/d9kh6s92%28v=VS.80%29.aspx
    7. http://social.msdn.microsoft.com/Forums/zh-CN/1761/thread/cf455160-e3ea-4f06-9683-72ff2862946f
    Tags:  为什么要分手 为什么要结婚 人为什么要睡觉 姚明为什么要退役

    延伸阅读

    最新评论

    发表评论