MEF系列一 : MEF简介及解决什么问题

首先,什么是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)将执行如下操作:

  1. 找出所有依赖项;
  2. 加载它们到内存;
  3. 映射它们到相应的指针;
  4. 启动主例程.

但在.NET环境中,中间有CLR和JIT机制,所以情况有些许不同.加载器只会加载Main方法中使用的那些类库,IL(Intermediate Language,中间语言)将Main方法中调用的其它方法在需要时即时编译(JIT)并加载到内存,这也是MEF的基础之一.

案例

下来看一个明显感觉到需要用到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;

    namespace WOMEFLib
    {
        public class Speak:ISpeak
        {
            public void SayHello()
            {
                Console.WriteLine("Hello World!");
            }
        }
    }

在WOMEF项目中添加对WOMEFLib项目的引用,解决方案中右键WOMEF项目,属性\生成\配置,选择”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,打开;
  3. 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
    
  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=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
    
  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 <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
  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;
  11. 双击 manifest,可以看到如下

当应用程序启动时缺少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 <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
    
  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 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()
    
  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. 这意味着,一旦程序启动,加载器将不会自动重新加载;
  5. 这就是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

时间: 2024-08-06 07:49:01

MEF系列一 : MEF简介及解决什么问题的相关文章

C#可扩展编程之MEF(五):MEF高级进阶

好久没有写博客了,今天抽空继续写MEF系列的文章.有园友提出这种系列的文章要做个目录,看起来方便,所以就抽空做了一个,放到每篇文章的最后. 前面四篇讲了MEF的基础知识,学完了前四篇,MEF中比较常用的基本已经讲完了,相信大家已经能看出MEF所带来的便利了.今天就介绍一些MEF中一些较为不常用的东西,也就是大家口中的所谓的比较高级的用法. 前面讲的导出都是在每个类上面添加Export注解,实现导出的,那么有没有一种比较简便的方法呢?答案是有的,就是在接口上面写注解,这样只要实现了这个接口的类都会

【 D3.js 入门系列 — 0 】 简介和安装

[ D3.js 入门系列 — 0 ] 简介和安装 发表于2014/06/12 近年来,可视化越来越流行,许多报刊杂志.门户网站.新闻.媒体都大量使用可视化技术,使得复杂的数据和文字变得十分容易理解,有一句谚语“一张图片价值于一千个字”,的确是名副其实.各种数据可视化工具也如井喷式地发展,D3 正是其中的佼佼者. 1. D3 是什么 D3 的全称是(Data-Driven Documents),顾名思义可以知道是一个被数据驱动的文档.听名字有点抽象,说简单一点,其实就是一个 JavaScript

MIFARE系列1——MIFARE简介

随着社会的发展,智能卡在很多领域得到了广泛的应用.特别是非接触卡,由于使用方便以及功能强大的特点,在管理.公交.工作证.身份识别等领域得到了快速的普及和推广. 非接触卡已经逐步发展成为一个独立的跨学科的专业领域.它将大量来自完全不同专业领域的技术综合到一起:如高频技术.电磁兼容性技术.半导体技术.数据保护和密码学.电信.制造技术和许多专业应用技术等. Mifare是NXP公司生产的一系列遵守ISO14443A标准的射频卡,包括Mifare S50.Mifare S70.Mifare UltraL

Juniper-HA SSG系列cluster-id 稀缺问题的解决办法

Juniper-HA SSG系列cluster-id 稀缺问题的解决办法. http://forums.juniper.net/t5/ScreenOS-Firewalls-NOT-SRX/Cluster-ID-issue-on-ssg140/m-p/15312//true (来自瞻博官方技术员的解答) By default, NSRP will support up to 8 cluster id's and 8 VSD's.  As noted in the previous entry, y

[JavaEE] IBM - Spring 系列: Spring 框架简介

Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级的.强壮的 J2EE 应用程序.developerWorks 的定期投稿人 Naveen Balani 通过介绍 Spring 框架开始了他由三部分组成的 Spring 系列,其中还将介绍 Spring 面向方面的编程(AOP)和控制反转(IOC)容器. Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一

Spring 系列: Spring 框架简介

Spring 是一个开源框架,是为了解决企业应用程序开发复杂性而创建的.框架的主要优势之一就是其分层架构,分层架构允许您选择使用哪一个组件,同时为 J2EE 应用程序开发提供集成的框架. 在这篇由三部分组成的 Spring 系列 的第 1 部分中,我将介绍 Spring 框架.我先从框架底层模型的角度描述该框架的功能,然后将讨论两个最有趣的模块:Spring 面向方面编程(AOP)和控制反转 (IOC) 容器.接着将使用几个示例演示 IOC 容器在典型应用程序用例场景中的应用情况.这些示例还将成

持久化API(JPA)系列(一)实体简介

J2EE规范制订了EntityBean规范来解决应用程序的持久化问题,但由于设计得过于复杂等缺陷,因此在EJB规范中饱受诟病. 随后,大量开源ORM框架(如Hibernate)出现.这些ORM框架不仅简单.易用,而且也可以面向对象的方式来操作关系数据库,并提供强大的数据查询功能.慢慢地,这些ORM框架不断替代EntityBean. 当Sun公司制订JavaEE5规范时,Sun公司彻底抛弃了原来的EntityBean,而是推出了新的JPA规范·Sun公司的JPA以Entity为核心,它将实体映射到

[转]Selenium私房菜系列1 -- Selenium简介

一.Selenium是什么? Selenium是ThroughtWorks公司一个强大的开源Web功能测试工具系列,本系列现在主要包括以下4款: 1.Selenium Core:支持DHTML的测试案例(效果类似数据驱动测试),它是Selenium  IDE和Selenium  RC的引擎. 2.Selenium IDE:FireFox的一个插件,支持脚本录制. 3.Selenium RC:Selenium Remote Control.后续的系列文章我会主要针对Selenium RC展开介绍.

ENode视频分享系列之- 架构简介和QuickStart例子分析

ENode是一个应用开发框架,为开发人员提供了一整套基于DDD+CQRS+ES+EDA架构风格的解决方案.ENode的最大特点是将并发降低到最低,并做到最大程度的并行:ENode的主要目标是解决CQRS架构的C端的高并发写的问题.ENode从发布1.0开始到现在的差不多两年多时间,我几乎每周都在更新设计和代码实现.以至于这两年来从来没有一个稳定的版本可以提供给大家,非常惭愧.但我相信,随着时间的推移和我的努力的积累,ENode一定会越来越稳定和成熟的,目前ENode的版本已经比较稳定了,如果有谁