首先,什么是MEF?
The Managed Extensibility Framework or MEF is a library for creating lightweight, extensible applications. It allows application developers to discover and use extensions with no configuration required. It also lets extension developers easily encapsulate code and avoid fragile hard dependencies. MEF not only allows extensions to be reused within applications, but across applications as well.
MEF(Managed Extensibility Framework)是一个用于创建可扩展的轻型应用程序的库。 应用程序开发人员可利用该库发现并使用扩展,而无需进行配置。 扩展开发人员还可以利用该库轻松地封装代码,避免生成脆弱的硬依赖项。 通过 MEF,不仅可以在应用程序内重用扩展,还可以在应用程序之间重用扩展。
MSDN中是这么说哒~根据定义,可以理解,MEF首先是一个库,可以用来创建可扩展的轻型应用程序,这个也可以接受。刚开始的时候,很多地方是有疑问的。
- 可以利用这个库发现并使用扩展,是怎么发现的?又是怎么使用的呢?
- 无需进行配置,为什么突然说不需要配置?在这个框架出来之前,有什么样的框架是需要配置才能使用?MEF又是在什么情况下为了解决什么而出现的呢?
- 利用这个库轻松封装代码,怎么封装?避免生成硬依赖项,怎么避免,什么是硬依赖项?
- 可以在程序内重用扩展,也可以在程序之间重用,怎么重用?
- 如何通信 ?
呵呵哒,好嘛,不懂。因为不懂,就想知道这个东西凭什么可以以这样的姿态出现。
以下内容转载自:为什么要MEF?
---------------------------------------------------------------------------------------------------------------------
通常,创建可重用的代码库并在程序中使用。在传统的Win32应用程序中,如果一个类库被引用至某个应用程序,连接器(Linker)在PE Header中添加此类库的引用。当运行时试图加载应用程序,加载器(Loader)将执行如下操作:
- 找出所有依赖项;
- 加载它们到内存;
- 映射它们到相应的指针;
- 启动主例程.
但在.NET环境中,中间有CLR和JIT机制,所以情况有些许不同.加载器只会加载Main方法中使用的那些类库,IL(Intermediate Language,中间语言)将Main方法中调用的其它方法在需要时即时编译(JIT)并加载到内存,这也是MEF的基础之一.
案例
下来看一个明显感觉到需要用到MEF的场景,创建一个控制台应用程序来达到此目的。
- 创建一个简单的控制台应用程序 “WOMEF”(Without MEF);
- 用如下代码替换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(); } } }
在新的类库项目中定义ISpeak和Speak:
- 在解决方案中添加类库项目 “WOMEFLib”;
- 删除Class1.cs;
- 添加接口ISpeak.cs;
namespace WOMEFLib { public interface ISpeak { void SayHello(); } }
- 添加接口的实现Speak.cs;
namespace WOMEFLib { public class Speak:ISpeak { public void SayHello() { Console.WriteLine("Hello World!"); } } }
在WOMEF项目中添加对WOMEFLib项目的引用,解决方案中右键WOMEF项目,属性\生成\配置,选择”Release”,保存、生成、调试,这都不是我们关注的重点,我们要关注的是这两个程序集的相关的问题。
我们将要验证以下几点:
- 加载器何时加载WOMEFLib.dll;
- 当应用程序启动时缺少WOMEFLib.dll时会怎样;
- Program.Speak方法何时被JIT编译;
- 第一次等待用户输入时将WOMEFLib.dll复制到程序所在目录会如何;
要验证以上几点,我们需要在运行时查看方法列表及程序集信息,以下将围绕这几点进行阐述。
需要用到的工具,Windbg,MSIL 反汇编程序,关于这两个工具可从 这里下载安装 。
有关SOS 调试扩展的资料可参考这里。
加载器何时加载WOMEFLib.dll
- 启动Windbg;
- 单击 File->Open executable,选择Release目录下WOMEF.exe,打开;
- Windbg 会停在断点int3处(WinDbg 会在调试目标的进程中创建一个远线程,并在这个远线程中执行 ntdll!DbgBreakPoint 函数,它会在目标进程中产生一次 int3 异常,这个异常被Windbg捕获,所以WOMEF.exe就中断到调试器中了),按F5继续;
Microsoft (R) Windows Debugger Version 6.12.0002.633 X86Copyright (c) Microsoft Corporation. All rights reserved. CommandLine: D:\Test\Test\WOMEF\bin\Release\WOMEF.exeSymbol 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.exeModLoad: 77570000 776ad000 ntdll.dllModLoad: 71aa0000 71aea000 C:\Windows\SYSTEM32\MSCOREE.DLLModLoad: 760c0000 76194000 C:\Windows\system32\KERNEL32.dllModLoad: 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=00000000eip=7760ebbe esp=001af688 ebp=001af6b4 iopl=0 nv up ei pl zr na pe nccs=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 30:000> gModLoad: 75eb0000 75f50000 C:\Windows\system32\ADVAPI32.dllModLoad: 75e00000 75eac000 C:\Windows\system32\msvcrt.dllModLoad: 76010000 76029000 C:\Windows\SYSTEM32\sechost.dllModLoad: 75d50000 75df1000 C:\Windows\system32\RPCRT4.dllModLoad: 71a30000 71a96000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dllModLoad: 761a0000 761f7000 C:\Windows\system32\SHLWAPI.dllModLoad: 77750000 7779e000 C:\Windows\system32\GDI32.dllModLoad: 75c80000 75d49000 C:\Windows\system32\USER32.dllModLoad: 776b0000 776ba000 C:\Windows\system32\LPK.dllModLoad: 774d0000 7756d000 C:\Windows\system32\USP10.dllModLoad: 75fe0000 75fff000 C:\Windows\system32\IMM32.DLLModLoad: 773b0000 7747c000 C:\Windows\system32\MSCTF.dllModLoad: 6d910000 6df80000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clr.dllModLoad: 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.dllModLoad: 6c5e0000 6c5f0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\nlssorting.dllModLoad: 76400000 7655c000 C:\Windows\system32\ole32.dllModLoad: 75640000 7564c000 C:\Windows\system32\CRYPTBASE.dllModLoad: 63b80000 63be0000 C:\Windows\Microsoft.NET\Framework\v4.0.30319\clrjit.dllModLoad: 003a0000 003a8000 WOMEFLib.dllModLoad: 004d0000 004d8000 WOMEFLib.dll
- 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
- 在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=00000000eip=775a3370 esp=012ffcd0 ebp=012ffcfc iopl=0 nv up ei pl zr na pe nccs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246ntdll!DbgBreakPoint:775a3370 cc int 3
- 加载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
- 在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 <symbol_path> argument when starting the debugger. ** using .sympath and .sympath+ **********************************************************************PDB symbol for clr.dll not loaded--------------------------------------System Domain: 6df03478LowFrequencyHeap: 6df03784HighFrequencyHeap: 6df037d0StubHeap: 6df0381cStage: OPENName: None--------------------------------------Shared Domain: 6df03140LowFrequencyHeap: 6df03784HighFrequencyHeap: 6df037d0StubHeap: 6df0381cStage: OPENName: NoneAssembly: 002462e8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]ClassLoader: 00246388 Module Name6c7d1000 C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll --------------------------------------Domain 1: 00201520LowFrequencyHeap: 0020189cHighFrequencyHeap: 002018e8StubHeap: 00201934Stage: OPENSecurityDescriptor: 00202c98Name: WOMEF.exeAssembly: 002462e8 [C:\Windows\Microsoft.Net\assembly\GAC_32\mscorlib\v4.0_4.0.0.0__b77a5c561934e089\mscorlib.dll]ClassLoader: 00246388SecurityDescriptor: 002460b8 Module Name6c7d1000 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: 00253628SecurityDescriptor: 00252dd8 Module Name001d2e9c D:\Test\Test\WOMEF\bin\Release\WOMEF.exe Assembly: 00262830 [D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll]ClassLoader: 002628d0SecurityDescriptor: 00255df8 Module Name001d38d0 D:\Test\Test\WOMEF\bin\Release\WOMEFLib.dll
- 在应用程序域中有三个程序集被加载,分别是mscorlib.dll、WOMEF.exe、WOMEFLib.dll,见粗体字部分;
- 可见加载器加载了引用的程序集WOMEFLib.dll,虽然还没有使用此dll中的任何类型,此刻执行到
ConsoleKeyInfo key = Console.ReadKey(true);
虽然还没有使用WOMEFLib.dll中的任何东西,但依然被加载,这是为什么呢?因为WOMEFLib.dll已经在WOMEF.exe的manifest中,请先关闭Windbg。
- 启动IL,打开WOMMEF.exe;
- 双击 manifest,可以看到如下
当应用程序启动时缺少WOMEFLib.dll时会怎样
接下来我们测试下当缺少WOMEFLib.dll时会发生什么,将Release目录中的WOMEFLib.dll剪贴到别的地方,如桌面,
- 启动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)
- 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
- 虽然依赖的程序集WOMEFLib.dll已经没有了,程序依然能够正常运行到此处,这点比较有趣,为什么加载器没有报”找不到WOMEFLib.dll”的错误呢?答案是Program.Speak()还没有被JIT编译,我们接下来将验证这一点,请先关闭Windbg。
Program.Speak方法何时被JIT编译
我们来验证下Program.Speak方法何时被JIT编译,将刚才移动到桌面的WOMEFLib.dll文件再次移动回到Release目录来
- 启动Windbg,File-> Open executable,打开Release目录下的WOMEF.exe,按F5继续;
- 此时,程序等待用户输入,显示为"按X键退出,否则继续." ;
- 在Windbg窗体中,单击菜单 Debug->Break(或者按Ctrl+Break);
- 加载CLR,在Windbg命令行中输入”.loadby sos clr”;
- 在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 <symbol_path> 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
- 此刻,程序运行至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
- 再来看看方法表的信息,在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()
- 可见,方法”WOMEF.Program.Speak()”的JIT状态为NONE,这意味这这个方法还没有被JIT编译,在Windbg中按F5继续运行,在控制台窗体程序中输入任意非’X’字符,CLR编译Program.Speak方法,加载WOMEFLib.dll中的Speak方法;
- 再次在Windbg中单击菜单 Debug->Break(或者按Ctrl+Break);
- 接着看看方法表信息,在Windbg命令行中输入”!dumpmt -md 00143810”,00143810是WOMEF.Program的地址,如上的红色字体处;
0:004> !dumpmt -md 00143810EEClass: 00141424Module: 00142e9cName: WOMEF.ProgrammdToken: 02000002File: D:\Test\Test\WOMEF\bin\Release\WOMEF.exeBaseSize: 0xcComponentSize: 0x0Slots in VTable: 7Number of IFaces in IFaceMap: 0--------------------------------------MethodDesc Table Entry MethodDesc JIT Name6c9fa7e0 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()
- 如上,可看到WOMEF.Program.Speak的JIT状态为JIT,需要注意的一点是,若在第8步处按了X键,则WOMEF.Program.Speak不会被JIT编译。因此,当程序走到while循环体内,CLR即时编译并调用方法。
- 接下来我们来看看另外一种情景,当控制台程序运行到while循环体之前时,将WOMEFLib.dll复制到Release目录时会是什么状况,先关闭Windbg.
第一次等待用户输入时将WOMEFLib.dll复制到程序所在目录会如何
将Release目录中的WOMEFLib.dll剪贴到别的地方,如桌面
- 启动Windbg,File-> Open executable,打开Release目录下的WOMEF.exe,按F5继续;
- 此时,程序等待用户输入,显示为"按X键退出,否则继续." ,此时将WOMEFLib.dll移动回Release目录中;
- 输入任意非’X’字符,此时将会报错,如下:
- 这意味着,一旦程序启动,加载器将不会自动重新加载;
- 这就是MEF要解决的问题。
以前的解决方案
以上这些只是想让您更加清楚MEF要解决的问题,在开始用MEF之前,先看看如何用现有的技术来解决。在CLR2.0中我们可以在运行时加载程序集,加载后,我们可以创建程序集中定义的某类型的实例,比较简单,如下,在WOMEF项目中移除对WOMEFLib项目的引用,将Program.cs替换为如下代码:
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方法。
以上内容转载自:http://www.cyqdata.com/cnblogs/article-detail-41697