C#程序集系列05,讓程序集包含多個module


本篇體驗在一個程序集中包含多個module。

 

□ 創建3個module

→刪除F盤as文件夾中的一些文件,只剩下如下3個文件
27
→用記事本打開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
28
→把MySecondModule.cs類編譯成module
29
→在F盤as文件夾中創建MyThirdModule.cs文件,用記事本打開編寫如下代碼,並保存

using System;
public class MyThirdModule
{
    public static void Hello()
    {
        Console.WriteLine("來自module 3的問候~");
    }
}


→把MyThirdModule.cs類編譯成module
30

 

□ 創建2個程序集並引用運行

現在需要創建2個程序集,一個程序集中包含MyFirstModule和MySecondModule。另一個程序集包含MySecondModule和MyThirdModule。

→創建程序集AssemblyA.dll包含MyFirstModule和MySecondModule。
31
→創建程序集AssemblyB.dll包含MySecondModule和MyThirdModule。
32
→編譯MainClass.cs文件,引用AssemblyA.dll程序集
33
以上的dos命令等同於:csc /r:AssemblyA.dll /out:MainClass.exe MainClass.cs
→運行MainClass.exe
34
→修改MainClass.cs文件

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

→編譯MainClass.cs,引用AssemblyB.dll程序集
35
→運行MainClassAnother.exe
36

 

總結:一個程序集是可以包含多個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

117

→把MySecondModule.cs編譯成module

118

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

119

→在as文件夾下創建MainClass.cs文件,修改如下,並保存

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

其中只用到了一個module。

→編譯MainClass.cs文件,引用MyAssembly.dll文件

120

→運行MainClass.exe

121

→反編譯MainClass.exe可執行文件,並輸出到記事本查看IL代碼

122

 

// 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

123

 

// 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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM