11.4 构建和使用多文件程序集
现在已经构建和使用了单文件程序集,下面开始构建一个多文件程序集。前面已经介绍过,多文件程序集是相关模块的集合,这些模块作为一个单元被部署和版本化。在编写本书的时候,Visual Studio 2005并不支持C#多文件程序集的项目模板,因此如果一定要构建它的话,那就只能使用命令行编译器(csc.exe)。
我们将会创建一个名为AirVehicles的多文件程序集。其主模块airvehicles.dll只包含一个Helicopter类类型。其关联的清单(同样包含在airvehicles.dll中)列出了一个名为ufo.netmodule的额外文件,该文件包含了另外一个类类型Ufo。尽管两个类类型物理上被包含在两个二进制文件中,但我们把它们放到同一个命名空间(AirVehicles)下。两个类都将使用C#编写(当然,也可以混合搭配其他的语言)。
首先,打开一个简单的文本编辑器(例如Notepad记事本),然后编写类Ufo的定义,保存到ufo.cs文件中:
using System;
namespace AirVehicles
{
public class Ufo
{
public void AbductHuman()
{
Console.WriteLine("Resistance is futile");
}
}
}
把该类编译成一个.NET的模块,导航到包含ufo.cs文件的文件夹,然后使用C#编译器执行以下命令(/target标记的module选项通知csc.exe去生成一个*.netmodule文件而不是*.dll或者*.exe文件):
csc.exe /t:module ufo.cs
现在查看一下含有ufo.cs文件的文件夹,应该会发现一个名为ufo.netmodule的新文件。接着创建一个名为helicopter.cs的新文件,该文件包含如下类定义:
using System;
namespace AirVehicles
{
public class Helicopter
{
public void TakeOff()
{
Console.WriteLine("Helicopter taking off!");
}
}
}
由于已经决定了该多文件程序集的主模块名为airvehicles.dll,因此需要使用/t:library和/out:选项来编译helicopter.cs。同时,为了把ufo.netmodule二进制文件添加到程序集的清单中,还需要指定/addmodule标记。请看以下命令:
csc /t:library /addmodule:ufo.netmodule /out:airvehicles.dll helicopter.cs
现在,目录里面应该含有主模块airvehicles.dll和辅助模块ufo.netmodule两个二进制文件。
11.4.1 ufo.netmodule文件
使用ildasm.exe打开ufo.netmodule文件。会看到*.netmodule文件含有一个模块级别的清单。该清单的唯一目的是用于列举该代码库引用的外部程序集。由于Ufo类只是调用了Console.WriteLine()方法,你将会看到以下内容:
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
.module ufo.netmodule
11.4.2 airvehicles.dll文件
继续使用ildasm.exe打开主模块airvehicles.dll模块,查看其程序集级别的清单。其中.file标记记录了多文件程序集中的关联模块(此处为ufo.netmodule)。.class外部标记则记录了主模块从辅助模块(Ufo)中引用的外部类型名。
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
.ver 2:0:0:0
}
.assembly airvehicles
{
...
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.file ufo.netmodule
...
.class extern public AirVehicles.Ufo
{
.file ufo.netmodule
.class 0x02000002
}
.module airvehicles.dll
请注意,airvehicles.dll和ufo.netmodule并没有被合并为一个*.dll文件,它们只是通过程序集清单连接起来。
11.4.3 使用多文件程序集
使用多文件程序集时,必须注意:引用的程序集是由多个模块组成的。为了阐述如何使用多文件程序集,让我们在命令行环境下创建一个Visual Basic .NET客户端应用程序。使用如下模块定义创建一个名为Client.vb的新文件,把它保存到多文件程序集所处的目录下。
Imports AirVehicles
Module Module1
Sub Main()
Dim h As New AirVehicles.Helicopter()
h.TakeOff()
‘此处将会按需加载*.netmodule。
Dim u As New UFO()
u.AbductHuman()
End Sub
End Module
在命令行环境下使用Visual Basic .NET命令行编译器vbc.exe,编译这个可执行程序集,具体命令如下:
vbc /r:airvehicles.dll *.vb
从上面的命令可以看出,引用多文件程序集,只需要向编译器提供主模块的名称就可以了(客户端代码会按需加载*.netmodules辅助模块)。需要注意的是,*.netmodules没有自己的独立版本号,因此CLR不能直接加载它们。每个*.netmodules模块仅能够通过主模块才能被加载(因为主模块含有程序集清单)。
注解 Visual Studio 2005也支持引用多文件程序集。只需打开Add References对话框,选择主模块,那么任何相关的*.netmodules也将被复制到项目中。
至此,对读者来说,创建单文件程序集和多文件程序集都已不在话下。但老实说,可能99.99%的程序集都是单文件程序集。虽然如此,多文件程序集可以帮助我们把大的二进制程序集分拆为更细的单元(这对于远程下载非常有用)。接下来,我们开始学习私有程序集的概念。
源代码 MultifileAssembly项目的源代码位于Chapter 11子目录下。






