本篇体验在一个程序集中包含多个module。

□ 创建3个module

→删除F盘as文件夹中的一些文件,只剩下如下3个文件

→用记事本打开MyFirstModule.cs文件,修改如下,并保存

using System;

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

→用记事本打开MySecondModule.cs文件,修改如下,并保存

using System;

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

→把MyFirstModule.cs类编译成module

→把MySecondModule.cs类编译成module

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

using System;

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

→把MyThirdModule.cs类编译成module

□ 创建2个程序集并引用运行

现在需要创建2个程序集,一个程序集中包含MyFirstModule和MySecondModule。另一个程序集包含MySecondModule和MyThirdModule。

→创建程序集AssemblyA.dll包含MyFirstModule和MySecondModule。

→创建程序集AssemblyB.dll包含MySecondModule和MyThirdModule。

→编译MainClass.cs文件,引用AssemblyA.dll程序集

以上的dos命令等同于:csc /r:AssemblyA.dll /out:MainClass.exe MainClass.cs
→运行MainClass.exe

→修改MainClass.cs文件

using System;

using System;

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


→编译MainClass.cs,引用AssemblyB.dll程序集

→运行MainClassAnother.exe

总结:一个程序集是可以包含多个module的。如果将不常用的代码放在单独的module中,就可以减少程序集的载入时间。如果通过网络下载程序集,还可以节约带宽。

关于1楼stg609的问题

问:上面代码中 module1 和 2 是什么时候加载到客户端的?

我们来求证一下:

→删除F盘as文件夹内的所有文件

→在as文件夹下创建MyFirstModule.cs文件,修改如下,并保存

using System;

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

→在as文件夹下创建MySecondModule.cs文件,修改如下,并保存

using System;

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

→把MyFirstModule.cs编译成module

→把MySecondModule.cs编译成module

→创建程序集,把MyFirstModule和MySecondModule包含其中

→在as文件夹下创建MainClass.cs文件,修改如下,并保存

using System;

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

其中只用到了一个module。

→编译MainClass.cs文件,引用MyAssembly.dll文件

→运行MainClass.exe

→反编译MainClass.exe可执行文件,并输出到记事本查看IL代码

// 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
}
.assembly extern MyAssembly
{
  .ver 0:0:0:0
}
.assembly MainClass
{
  .custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
  .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.
  .hash algorithm 0x00008004
  .ver 0:0:0:0
}
.module MainClass.exe
// MVID: {7A00D175-6AB5-4EE8-BDDF-EEA3FC87EABD}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x003B0000


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

.class private auto ansi beforefieldinit MainClass
       extends [mscorlib]System.Object
{
  .method private hidebysig static void  Main() cil managed
  {
    .entrypoint
    // 代码大小       8 (0x8)
    .maxstack  8
    IL_0000:  nop
    IL_0001:  call       void [MyAssembly]MyFirstModule::Hello()
    IL_0006:  nop
    IL_0007:  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

○ .assembly extern MyAssembly,说明MainClass.exe引用了外部程序集MyAssembly.dll

○ void [MyAssembly]MyFirstModule::Hello(),说明MainClass.exe调用了MyAssembly程序集的Hello方法

可是,依然无法看出2个module是否已经被加载到MyAssembly程序集中!

→反编译MyAssembly.dll

// 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
}
.assembly MyAssembly
{
  .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 = (ED 03 41 CA 3F 61 8C 1C FB 06 F2 05 8E 72 9B 86   // ..A.?a.......r..
             AE 99 CA 28 )                                     // ...(
.file MySecondModule.netmodule
    .hash = (B0 B3 96 5D C5 9D 56 C6 12 00 6E 03 DF 60 EA 9C   // ...]..V...n..`..
             2F 87 A6 FE )                                     // /...
.class extern public MyFirstModule
{
  .file MyFirstModule.netmodule
  .class 0x02000002
}
.class extern public MySecondModule
{
  .file MySecondModule.netmodule
  .class 0x02000002
}
.module MyAssembly.dll
// MVID: {BBC0A811-A24C-4C47-8C24-5A7B96E114C8}
.imagebase 0x10000000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003       // WINDOWS_CUI
.corflags 0x00000001    //  ILONLY
// Image base: 0x003C0000

○  .module MyAssembly.dll,说明MyAssembly.dll中只有一个与程序集名称一致的一个module,FirstModule和SecondModule去哪了?

○ .file MyFirstModule.netmodule,原来FirstModule是作为MyAssembly.dll的外部文件存在的,即当程序集需要MyFirstModule的时候,再去加载。

○ .file MySecondModule.netmodule,SecondModule也是作为MyAssembly.dll的外部文件存在。

至此,就可以回答stg609的问题了:

当客户端调用程序集某个module的方法时,才去加载方法所在的module。因为module1和module2是以外部文件的形式存在于同一个程序集中的,当客户端调用module1的方法,module1才被加载。

“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#程序集系列05,让程序集包含多个module的更多相关文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    CLR在加载程序集的时候会查看程序集清单,程序集清单包含哪些内容呢?可执行文件和程序集有什么区别/ 程序集清单 □ 查看程序集清单 →清空F盘as文件夹中的所有内容→创建MainClass.cs文件→ ...

随机推荐

  1. FZU 1901 Period II(KMP循环节+公共前后缀)

    题目链接:http://acm.fzu.edu.cn/problem.php?pid=1901 题目大意:题目大意求出所有p满足s[i]=s[i+p](i<=len-p) 解题思路: 其实就是要 ...

  2. Ubuntu 搭建ELK

    一.简介 官网地址:https://www.elastic.co/cn/ 官网权威指南:https://www.elastic.co/guide/cn/elasticsearch/guide/curr ...

  3. web项目引入extjs小例子

    一个新的项目,前端用extjs实现!分享一下extjs开发的准备工作! 首先去下载extjs的资源包,这里我是随便在网上下载的! 打开之后 ,目录是这样的! 需要关注的几个文件夹: builds:压缩 ...

  4. easyUI小技巧-纯干货

    一.显示分页(pagination:true)情况下,隐藏每页显示的记录条数的那个select(即pageList),下图箭头 方法1:onBeforeLoad:function(param){    ...

  5. LoadRunner 11简单使用

    LoadRunner 11简单使用 开始菜单-->HP LoadRunner-->applications--->virtual user Generator 1>新建--&g ...

  6. CentOS源码安装搭建LNMP全过程(包括nginx,mysql,php,svn)

    服务器环境为:CentOS6.5 64位 目标:搭建LNMP(Linux + Nginx + MySQL + PHP +SVN),其中svn是用来代替ftp,方便开发中调试同步代码 相关目录:所有软件 ...

  7. [CodeForces]CodeForces - 1025F Disjoint Triangles

    题意: 给出平面上n个点,问能在其中选出6个点,组成两个三角形,使得其互不相交 问有多少种选法 大致思路  考虑枚举一条直线,将所有得点分为左右两部分,其中有两个点在直线上, 以这两个点为顶点,分别统 ...

  8. IOS和Android音频开发总结

    最近因为项目需要对声音进行变声,所以边学习边做,发现音频的处理思路并不难,但是做起来还是有些繁琐的(比预期的) 趁着脑子还发热,赶紧把思路总结一下,记录下来. 主要讲三个部分 1,如何变声2,安卓实现 ...

  9. My blog in AI ---神经网络,神经元(neural network,nervecell)

    尽管我们有很多经验丰富的软件开发人员,但是利用hard code的方法,要解决一些问题,我们的程序员还是优点捉襟见肘,这些问题包括,识别手写数字照片上的数字:分辨一张彩色照片上是否有一只猫咪:准确理解 ...

  10. linux安装及配置c++的opencv库

    linux安装及配置c++的opencv库 前言: 最近想搞个机器视觉的比赛,要求是linux+opencv环境,没有做过opencv开发的我配置环境就配了两天,看来很多乱七八糟的博客,终于装好了.网 ...