要将 ufo.cs 编译为 .NET 模块,请指定 /t:module 作为目标类型,这会自动遵循 *.netmodule 命名约定(请回想一下,默认的响应文件自动引用 System.Windows.Forms.dll,因此我们不需要显式引用该库):
csc /t:module ufo.cs如果您要将 ufo.netmodule 加载到 ildasm.exe 中,您会发现一个记载了该模块的名称和外部引用程序集的模块级别清单(请注意,*.netmodules 没有指定版本号,因为那是主模块的工作):
.assembly extern mscorlib{...} .assembly extern System.Windows.Forms{...} .module ufo.netmodule现在,请创建一个名为 helicopter.cs 的新文件,该文件将用于编译主模块 Airvehicles.dll:
// helicopter.cs using System; using System.Windows.Forms; namespace AirVehicles { public class Helicopter { public void TakeOff() { MessageBox.Show("Helicopter taking off!"); } } }假设 Airvehicles.dll 是该多文件程序集的主模块,则您将需要指定 /t:library 标志。但是,因为您还希望将 ufo.netmodule 二进制文件编码到程序集清单中,所以您还必须指定 /addmodule 选项:
csc /t:library /addmodule:ufo.netmodule /out:airvehicles.dll helicopter.cs如果您要分析 airvehicles.dll 二进制文件内部包含的程序集级别清单(使用 ildasm.exe),则会发现 ufo.netmodule 确实是使用 .file CIL 指令记录的:
.assembly airvehicles{...} .file ufo.netmodule多文件程序集的使用者可以较少关心他们要引用的程序集由大量二进制文件组成这一事实。实际上,在句法上将看起来与使用单文件程序集的行为完全相同。为了使本文变得更有趣一些,让我们创建一个基于 Windows 窗体的客户端应用程序。
我们的下一个示例项目将是一个使用 airvehicles.dll多文件程序集的 Windows 窗体应用程序。在 C:\MyCSharpCode 目录中创建一个名为 WinFormClient 的新的子目录。创建一个派生自 Form 的类,该类定义了单个 Button 类型,当它被单击时,将创建 Helicopter 和 UFO 类型,并且调用它们的成员:
using System; using System.Windows.Forms; using AirVehicles; public class MyForm : Form { private Button btnUseVehicles = new Button(); public MyForm() { this.Text = "My Multifile Asm Client"; btnUseVehicles.Text = "Click Me"; btnUseVehicles.Width = 100; btnUseVehicles.Height = 100; btnUseVehicles.Top = 10; btnUseVehicles.Left = 10; btnUseVehicles.Click += new EventHandler(btnUseVehicles_Click); this.Controls.Add(btnUseVehicles); } private void btnUseVehicles_Click(object o, EventArgs e) { Helicopter h = new Helicopter(); h.TakeOff(); UFO u = new UFO(); u.AbductHuman(); } private static void Main() { Application.Run(new MyForm()); } }注 在继续操作之前,请确保将 airvehicals.dll 和 ufo.netmodule 二进制文件复制到 WinFormClient 目录中。
要将该应用程序编译为 Windows 窗体可执行文件,请确保指定 winexe 作为 /target 标志的修饰。请注意,在引用多文件程序集时,只须指定主模块的名称:
csc /t:winexe /r:airvehicles.dll *.cs在运行您的程序并单击按钮之后,您就应当看到按照预期显示的每个消息框。图 9 显示了我创建的一个消息框。
图 9. 示例消息框
下一个议程是分析如何使用 csc.exe 将资源(例如,字符串表或图像文件)嵌入到 .NET 程序集中。首先,可以使用 /win32Icon 选项指定 Win32 *.ico 文件的路径。假设您已经将一个名为 HappyDude.ico 的图标文件放到当前 Windows 窗体应用程序的应用程序目录中。要将 HappyDude.ico 设置为可执行文件的图标,请发出以下命令集:
csc /t:winexe /win32icon:HappyDude.ico /r:airvehicles.dll *.cs此时,应当更新可执行程序集,如图 10 所示。
图 10. 经过更新的可执行程序集
除了使用 /win32icon 分配应用程序图标以外,csc.exe 还提供了三个附加的以资源为中心的选项(表 5)。
表 5. csc.exe 的以资源为中心的选项
csc.exe 的以资源为中心的选项
定义
/resource
将 *.resources 文件内部包含的资源嵌入到当前程序集中。请注意,通过该选项可以“以公共方式”嵌入资源以供所有使用者使用,或者“以私有方式”嵌入资源以便仅供包含程序集使用。
/linkresource
在程序集清单中记录指向外部资源文件的链接,但实际上并不嵌入资源自身。
/win32res
使您可以嵌入存在于旧式 *.res 文件中的资源。