认识程序集:1. 程序集的生成
程序集(Assembly)是.NET程序的最小组成单位。每个程序集都有自己的名称、版本等信息。程序集通常表现为一个文件(.exe或.dll文件),这样的程序集被称为单文件程序集,这种程序集是最常见的。程序集也可以由多个文件组成,每个文件都是一个模块文件或者是一个资源文件,这样的程序集被称为多文件程序集。下面来了解一下如何生成单文件程序集和多文件程序集。
1. 单文件程序集的生成
这是最常见的程序集,使用 Visual Studio 只能生成单文件程序集。使用 csc.exe 能够很轻松地生成单文件程序集:
csc.exe /target:library /resource:Hello.jpg Hello.cs
上述命令执行后,会生成一个名为 Hello.dll 的文件,该文件组成了单文件程序集。这个文件是一个托管模块,存储了类型元数据和中间语言,还嵌入了资源文件 Hello.jpg 的内容(通过使用 /resource 选项)。类型元数据描述了模块中定义的类型及其成员,中间语言是编译后的托管代码。
程序集本身其实是一个逻辑概念,对于自身的描述是通过程序集清单来实现的。程序集清单是一种元数据,描述了程序集的名称、版本、区域性和强名称信息,还包括组成程序集的文件的列表和资源信息,以及其他信息。在单文件程序集中,程序集清单的元数据直接保存在主模块文件中。
在本例中,程序集中的名称是Hello,版本没有提供,默认为0.0.0.0,区域性为语言中立,强名称信息为空,文件列表只有Hello.exe,托管资源为Hello.jpg。
2. 多文件程序集的生成
多文件程序集比较少见,而且除了使用 csc.exe 之外,有时还需要使用 AL.exe。假设有两个源代码文件 A.cs 和 B.cs,我们有两种生成多文件程序集的方法,这两种方法的主要区别在于程序集清单是存储在某个模块中还是单独存储于主模块中。
先看第一种方法,只使用csc.exe就可以了:
csc.exe /target:module A.cs
csc.exe /target:library /addmodule.A.netmodule /out:Hello.dll B.cs
第一个命令将 A.cs 编译为一个模块文件,A.netmodule,该文件仅包含类型元数据和中间语言,不包含程序集清单,是一种“原始”的模块文件,不能独立存在,必须从属于程序集。第二个命令将 B.cs 编译成模块文件,Hello.dll。这个文件除了包含类型元数据和中间语言之外,还存储了程序集清单,因为成为主模块文件。此时,程序集的名称仍然为 Hello,但文件列表的内容变成了两个:A.netmodule 和 Hello.dll。
再来看第二种方法,需要使用 csc.exe 和 al.exe 两个命令:
csc /target:module A.cs
csc /target:module B.cs
al.exe /target:library /out:Hello.dll A.netmodule B.netmodule
前两个命令将 A.cs 和 B.cs 编译为两个“原始”的模块文件,A.netmodule 和 B.netmodule。第三个命令使用了AL.exe(Assembly Linker,程序集链接器),该命令能够将 A.netmodule 和 B.netmodule 组合到程序集中。这样,最终会生成 Hello.dll 这个主模块文件,该文件将仅包含程序集清单。在这个程序集清单中,文件列表的内容变成了三个:A.netmodule,B.netmodule 和 Hello.dll。
多文件程序集不仅生成麻烦,而且应用似乎也不是很广泛,因为对于CLR来说,它只认识程序集,所以部署的时候,都是以程序集作为最小单位。一旦某个“原始”模块发生了改变,整个程序集都必须重新生成。另外,只有程序集有版本,模块作为程序集的组成部分,不能被版本化。