大家好,欢迎来到IT知识分享网。
本篇体验在一个程序集中包含多个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的问候~");
}}
□ 创建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..WrapNonEx63 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 MainClassextends [mscorlib]System.Object{.method private hidebysig static void Main() cil managed{.entrypoint// 代码大小 8 (0x8)
.maxstack 8IL_0000: nopIL_0001: call void [MyAssembly]MyFirstModule::Hello()
IL_0006: nopIL_0007: ret} // end of method MainClass::Main
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{// 代码大小 7 (0x7)
.maxstack 8IL_0000: ldarg.0IL_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..WrapNonEx63 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
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/34242.html