多文件程序集

6
有一个单文件程序集的物理编码是由多个.cs文件组成的,而多文件程序集则有多个.Net模块。它们之间有什么区别和优势呢?
我的教授说,在这些程序集加载或jitting期间,可能会发现差异。并不是所有多文件程序集的.Net模块都会一次性加载。但他自己也不确定。请问有人能给我解释一下吗?
1个回答

10
假设我们有两个名为 RUT.csFUT.cs 的 .cs 文件,其中 RUT.cs 包含很少使用的类型,而 FUT.cs 包含经常使用的类型。现在运行 csc /t:module RUT.cs 命令,会导致 C# 编译器创建一个 RUT.netmodule 文件。这个文件是标准的 DLL PE 文件,但 CLR 不能单独加载它。
接下来,让我们将经常使用的类型编译成它们自己的模块。因为这些类型被经常使用,所以我们将把这个模块作为程序集清单的保管者。实际上,由于这个模块现在代表整个程序集,我将更改输出文件的名称为 JeffTypes.dll,而不是 FUT.dll。
csc /out:JeffTypes.dll /t:library /addmodule:RUT.netmodule FUT.cs

这一行告诉C#编译器编译FUT.cs文件以生成JeffTypes.dll文件。由于指定了/t:library,因此会在JeffTypes.dll文件中发出包含清单元数据表的DLL PE文件。/addmodule:RUT.netmodule开关告诉编译器RUT.netmodule是应该被视为程序集的一部分的文件。具体来说,/addmodule开关告诉编译器将文件添加到FileDef清单元数据表中,并将RUT.netmodule的公共导出类型添加到ExportedTypesDef清单元数据表中。enter image description here RUT.netmodule文件包含编译RUT.cs生成的IL代码。此文件还包含描述由RUT.cs定义的类型、方法、字段、属性、事件等的元数据表。元数据表还描述了RUT.cs引用的类型、方法等。JeffTypes.dll是一个单独的文件。与RUT.netmodule类似,该文件包括编译FUT.cs生成的IL代码,并包括类似的定义和引用元数据表。然而,JeffTypes.dll包含额外的清单元数据表,使其成为一个程序集。额外的清单元数据表描述组成程序集的所有文件(JeffTypes.dll文件本身和RUT.netmodule文件)。清单元数据表还包括从JeffTypes.dll和RUT.netmodule导出的所有公共类型。
现在,如果一些客户端代码引用了JeffTypes.dll并正在执行, 当第一次调用方法时,CLR检测方法作为参数、返回值或局部变量所引用的类型。然后,CLR尝试加载包含清单的引用程序集文件。如果正在访问的类型在该文件中,则CLR执行其内部簿记,允许使用该类型。如果清单指示所引用的类型在另一个文件中,则CLR尝试加载必要的文件,执行其内部簿记,并允许访问该类型。仅当调用引用未加载程序集中的类型的方法时,CLR才会加载程序集文件。

这意味着要运行应用程序,不需要存在所有来自引用程序集的文件。
因此,很少使用的源类可以编译为NetModules,并在需要时进行加载,提高性能和减小Dll文件大小,简化更改管理和部署过程。

图片和部分引文来自 jeffrey richter


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接