我们经常在项目中引用程序集。通常情况下,一个程序集包含一个module,但一个程序集也可以包含多个module。本篇就来体验:在一个可以被编译成.exe可执行文件的.cs文件中引用多个module。

□ 创建第一个module
→在前面2篇文章中,F盘的as文件夹中存放了若干程序集等文件。
→打开"VS2012开发人员命令提示",输入如下命令,最终清空了F盘的as文件夹中的所有内容

→在F盘的as文件夹中创建MyFirstModule.cs,用记事本打开编写如下代码,并保存

using System;

class MyFirstModule
{
    public static void Hello()
    {
        Console.WriteLine("来自module 1的问候~");
    }
}

→在"VS2012开发人员命令提示",输入如下命令,把类编译成module,按回车

→输入如下命令,发现F盘的as文件夹中多了一个MyFirstModule.netmodule文件

→输入如下命令,反编译生成的module,把module的IL代码放到1.txt文件中查看,按回车

→输入如下命令,打开1.txt文件

// Metadata version: v4.0.30319
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.module MyFirstModule.netmodule
// MVID: {4403DD3C-6C5D-4AD7-AAD4-2929F36C0F4F}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x00440000


// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi beforefieldinit MyFirstModule
       extends [mscorlib]System.Object
{
  .method public hidebysig static void  Hello() cil managed
  {
    // 代码大小       13 (0xd)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  ldstr      bytearray (65 67 EA 81 6D 00 6F 00 64 00 75 00 6C 00 65 00   // eg..m.o.d.u.l.e.
                                    20 00 31 00 84 76 EE 95 19 50 7E 00 )             //  .1..v...P~.
    IL_0006:  call       void [mscorlib]System.Console::WriteLine(string)
    IL_000b:  nop
    IL_000c:  ret
  } // end of method MyFirstModule::Hello

  .method public hidebysig specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // 代码大小       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method MyFirstModule::.ctor

} // end of class MyFirstModule


○ .assembly extern mscorlib,说明module用到了外部的mscorlib程序集
○ .module MyFirstModule.netmodule,表示modlue的名称是MyFirstModule.netmodule
○ .class...,表示module中的类

□ 创建第二个module

→在F盘的as文件夹中创建MySecondModule.cs,用记事本打开编写如下代码,并保存

using System;

class MySecondModule
{
    public static void Hello()
    {
        Console.WriteLine("来自module 2的问候~");
    }
}

→在"VS2012开发人员命令提示",输入如下命令,把类编译成module,按回车

□ 引用多个module

→在F盘的as文件夹中创建MainClass.cs,用记事本打开编写如下代码,并保存

using System;

class MainClass
{
    static void Main()
    {
        MyFirstModule.Hello();
        MySecondModule.Hello();
    }
}

→输入如下命令,编译MainClass.cs,并引入2个module

→输入如下命令,运行MainClass.exe

→输入如下命令,反编译MainClass.exe,把它的IL代码呈现到2.txt文件中

→输入如下命令,打开2.txt文件

// Metadata version: v4.0.30319
.module extern MyFirstModule.netmodule
.module extern MySecondModule.netmodule
.assembly extern mscorlib
{
  .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )                         // .z\V.4..
  .ver 4:0:0:0
}
.assembly MainClass
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78   // ....T..WrapNonEx
                                                                                                             63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )       // ceptionThrows.
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.file MyFirstModule.netmodule
    .hash = (2F 9D 95 85 6E F4 D2 CA 50 61 C0 9F A1 58 C6 5F   // /...n...Pa...X._
             5D 1D 96 4B )                                     // ]..K
.file MySecondModule.netmodule
    .hash = (28 72 47 EE 2E 76 45 AA 6B 87 17 93 6B 4F 1C 5D   // (rG..vE.k...kO.]
             84 D8 07 CB )
.module MainClass.exe
// MVID: {FD4741CB-DEDE-4D91-9B95-16DAF3CEB47E}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x003A0000


// =============== CLASS MEMBERS DECLARATION ===================

.class private auto ansi beforefieldinit MainClass
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    // 代码大小       14 (0xe)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  call       void [.module MyFirstModule.netmodule]MyFirstModule::Hello()
    IL_0006:  nop
    IL_0007:  call       void [.module MySecondModule.netmodule]MySecondModule::Hello()
    IL_000c:  nop
    IL_000d:  ret
  } // end of method MainClass::Main

  .method public hidebysig specialname rtspecialname
          instance void  .ctor() cil managed
  {
    // 代码大小       7 (0x7)
    .maxstack  8
    IL_0000:  ldarg.0
    IL_0001:  call       instance void [mscorlib]System.Object::.ctor()
    IL_0006:  ret
  } // end of method MainClass::.ctor

} // end of class MainClass


○ .module extern MyFirstModule.netmodule,引用了MyFirstModule这个module
○ .module extern MySecondModule.netmodule,引用了MySecondModule这个module
○ .assembly extern mscorlib,引用了.NET默认程序集mscorlib
○ .assembly MainClass,代表本程序集
○ .module MainClass.exe,说明MainClass本身包含了一个名称为MainClass.exe的module
○ .class...,表示程序集类

“C#程序集系列”包括:

C#程序集系列01,用记事本编写C#,IL代码,用DOS命令编译程序集,运行程序

C#程序集系列02,使用记事本查看可执行程序集的IL代码

C#程序集系列03,引用多个module

C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

C#程序集系列05,让程序集包含多个module

C#程序集系列06,程序集清单,EXE和DLL的区别

C#程序集系列07,篡改程序集

C#程序集系列08,设置程序集版本

C#程序集系列09,程序集签名

C#程序集系列10,强名称程序集

C#程序集系列11,全局程序集缓存

C#程序集系列12,C#编译器和CLR如何找寻程序集

C#程序集系列13,如何让CLR选择不同版本的程序集

参考资料:

http://www.computersciencevideos.org/  created by Jamie King

C#程序集系列03,引用多个module的更多相关文章

  1. C#程序集系列05,让程序集包含多个module

    本篇体验在一个程序集中包含多个module. □ 创建3个module →删除F盘as文件夹中的一些文件,只剩下如下3个文件→用记事本打开MyFirstModule.cs文件,修改如下,并保存 usi ...

  2. C#程序集系列04,在程序集包含多个module的场景下理解关键字internal

    本篇在一个程序集包含多个module的场景下体验internal的含义. →查看F盘as文件夹下的文件→删除MainClass.exe→把MyFirstModule和MySecondModule组装到 ...

  3. C#程序集系列13,如何让CLR选择不同版本的程序集

    本篇主要体验,在存在多个版本程序集的情况下,如何让CLR选择哪个版本程序集运行,以及程序集版本的切换. 分别生成非强名称程序集不同版本 □ 生成某个版本的程序集 →清理F盘as文件夹,剩下如下文件 → ...

  4. C#程序集系列12,C#编译器和CLR如何找寻程序集

    本篇体验C#编译器和CLR运行时如何查找程序集,并自定义CLR运行时查找程序集的方式. □ C#编译器和CLR运行时如何查找程序集 C#编译器在哪里?--在C:\Windows\Microsoft.N ...

  5. C#程序集系列11,全局程序集缓存

    全局程序集缓存(GAC:Global Assembly Cache)用来存放可能被多次使用的强名称程序集.当主程序需要加载程序集的时候,优先选择到全局程序集缓存中去找寻需要的程序集. 为什么需要全局程 ...

  6. C#程序集系列10,强名称程序集

    当一个程序集的名称,版本,文化,Public Key都做了设置,就可以把这个程序集叫做"强名称程序集".强名称程序集可以防止被仿冒或篡改.本篇首先创建一个强名称程序集,接着模拟篡改 ...

  7. C#程序集系列09,程序集签名

    在"C#程序集系列08,设置程序集版本"中体验了为程序集设置版本,但对于程序集的安全性来说,还远远不够.本篇体验程序集的签名. □ 程序集的签名 →F盘as文件夹下有多个文件→在程 ...

  8. C#程序集系列08,设置程序集版本

    区别一个程序集,不仅仅是程序集名称,还包括程序集版本.程序集公匙.程序集文化等,本篇体验通过界面和编码设置程序集版本. □ 通过Visual Studio设置程序集版本 →右键项目,选择"属 ...

  9. C#程序集系列07,篡改程序集

    以下几个方面用来区分不同的程序集:○ 程序集名称:Name○ 程序集版本:Version○ 程序集公匙: Public Token○ 程序集文化:Culture 如果没有很严格地按照上面的几个方面来创 ...

随机推荐

  1. thinkphp5高亮当前页(仅针对个人项目记录,不做通用参考)

    <div class="navbg"> <ul class="menu"> <li> <a href="/& ...

  2. MySQL权限问题

    1.修改MySQL用户密码 .先来看一个PASSWORD()函数,MYSQL使用MD5加密 SELECT PASSWORD(‘root’); .使用mysql数据库,查看用户表 USE mysql; ...

  3. gtk+学习笔记(六)

    今天用到了滚动窗口和微调按钮,根据网上的信息,简单总结下用法. 滚动窗口只能添加一个控件到其中 scrolled=gtk_scrolled_window_new(NULL,NULL); /*创建滚动窗 ...

  4. CodeIgniter典型的表单提交验证代码

    view内容: <?php echo form_open('user/reg'); ?> <h5>用户名</h5> <input type="tex ...

  5. CF 579A (二进制拆分)

    在培养皿中,每个细胞每天会繁殖,数量*2 我们可以在任意天加入任意数量的细胞入培养皿中. 想要知道最少加入多少个细胞,可以使得有一天,培养皿中细胞的数量会恰好为x 其实就是输出X的二进制中有多少个1 ...

  6. swftools中的pdf2swf转换Error overflow ID 65535 解决办法

    近几日因为项目需要在线转换pdf到swf实现电子期刊阅读,用到了这个工具,版本是:swftools-0.9.2.tar.gz 当然也遇到了很头疼的问题,那就是在转换pdf中色彩图形比较复杂的页时会抛出 ...

  7. 【洛谷】P2000 拯救世界

    题解 小迪的blog : https://www.cnblogs.com/RabbitHu/p/9178645.html 请大家点推荐并在sigongzi的评论下面点支持谢谢! 掌握了小迪生成函数的有 ...

  8. sql结合通配符来自定义转义字符

    1.使用   ESCAPE   关键字,定义转义符.在模式中,当转义符置于通配符之前时,该通配符就解释为普通字符.例如,要搜索在任意位置包含字符串   5%   的字符串,请使用:      WHER ...

  9. TypeScript的数据类型总结

    全局下载:npm i typescript -g 编译.ts文件:tsc  1.ts自动生成对应js文件 基本类型: 1.布尔,数字,字符串 ts文件 //布尔类型 var a:boolean=tru ...

  10. 使用 Web 服务 为 ECS Linux 实例配置网站及绑定域名

    Nginx 服务绑定域名 https://help.aliyun.com/knowledge_detail/41091.html?spm=a2c4e.11155515.0.0.4lvCpF 以 YUM ...