6

具有物理编码在多个 .cs 文件中的单个文件程序集与具有多个 .NetModules 的多文件程序集之间有什么区别和优势?

我的教授说,当这些程序集被加载或在 jitting 期间可以实现差异。并非多文件程序集的所有 .Netmodules 都会立即加载。但即使是他也不确定。有人可以澄清一下吗?

4

1 回答 1

10

假设我们有两个名为 .cs 的文件
RUT.cs,其中包含很少使用的类型
FUT.cs,其中包含经常使用的类型
Nowcsc /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,所以将包含清单元数据表的 DLL PE 文件发送到 JeffTypes.dll 文件中。/addmodule:RUT.netmodule 开关告诉编译器 RUT.netmodule 是一个应该被视为程序集一部分的文件。具体来说,/addmodule 开关告诉编译器将文件添加到 FileDef 清单元数据表,并将 RUT.netmodule 的公开导出类型添加到 ExportedTypesDef 清单元数据表。 在此处输入图像描述

RUT.netmodule 文件包含编译 RUT.cs 生成的 IL 代码。该文件还包含描述由 RUT.cs 定义的类型、方法、字段、属性、事件等的元数据表。元数据表还描述了 RUT.cs 引用的类型、方法等。JeffTypes.dll 是一个单独的文件。与 RUT.netmodule 一样,该文件包含编译 FUT.cs 生成的 IL 代码,还包含类似的定义和引用元数据表。但是,JeffTypes.dll 包含额外的清单元数据表,使 JeffTypes.dll 成为一个程序集。附加清单元数据表描述了构成程序集的所有文件(JeffTypes.dll 文件本身和 RUT.netmodule 文件)。清单元数据表还包括从 JeffTypes.dll 和 RUT 导出的所有公共类型。

现在,如果一些引用 JeffTypes.dll 的 clinet 代码正在执行,当第一次调用方法时,CLR 会检测方法引用的类型作为参数、返回值或局部变量。然后 CLR 尝试加载包含清单的引用程序集的文件。如果要访问的类型在此文件中,CLR 将执行其内部簿记,从而允许使用该类型。如果清单表明引用的类型在不同的文件中,CLR 会尝试加载必要的文件,执行其内部簿记,并允许访问该类型。仅当调用引用已卸载程序集中的类型的方法时,CLR 才加载程序集文件。

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

图片和杰弗里·里希特的一些 名言

于 2013-03-09T19:29:16.903 回答