如何构建多文件程序集

注释

本文特定于 .NET Framework。 它不适用于 .NET 的较新版本实现,包括 .NET 6 及更高版本。

本文介绍如何创建多文件程序集并提供说明过程中每个步骤的代码。

注释

适用于 C# 和 Visual Basic 的 Visual Studio IDE 只能用于创建单文件程序集。 如果要创建多文件程序集,则必须将命令行编译器或 Visual Studio 与 Visual C++配合使用。 仅 .NET Framework 支持多文件程序集。

创建多文件程序集

  1. 将所有包含程序集中其他模块引用的命名空间的文件编译为代码模块。 代码模块的默认扩展为 .netmodule

    例如,假设 Stringer 文件有一个命名空间 myStringer,其中包括一个类 Stringer。 该 Stringer 类包含一个名为 StringerMethod 的方法,该方法将单行写入控制台。

    // Assembly building example in the .NET Framework.
    using namespace System;
    
    namespace myStringer
    {
        public ref class Stringer
        {
        public:
            void StringerMethod()
            {
                System::Console::WriteLine("This is a line from StringerMethod.");
            }
        };
    }
    
    // Assembly building example in the .NET Framework.
    using System;
    
    namespace myStringer
    {
        public class Stringer
        {
            public void StringerMethod()
            {
                System.Console.WriteLine("This is a line from StringerMethod.");
            }
        }
    }
    
    ' Assembly building example in the .NET Framework.
    Namespace myStringer
        Public Class Stringer
            Public Sub StringerMethod()
                System.Console.WriteLine("This is a line from StringerMethod.")
            End Sub
        End Class
    End Namespace
    
  2. 使用以下命令编译此代码:

    cl /clr:pure /LN Stringer.cpp
    
    csc /t:module Stringer.cs
    
    vbc /t:module Stringer.vb
    

    使用编译器选项指定模块参数表示应将文件编译为模块而不是程序集。/t: 编译器生成一个名为 Stringer.netmodule 的模块,该模块可以添加到程序集。

  3. 使用必要的编译器选项编译所有其他模块,以指示代码中引用的其他模块。 此步骤使用 /addmodule 编译器选项。

    在以下示例中,名为 Client 的代码模块具有一个入口点 Main 方法,该方法引用在步骤 1 中创建的 Stringer.netmodule 模块中的方法。

    #using "Stringer.netmodule"
    
    using namespace System;
    using namespace myStringer; //The namespace created in Stringer.netmodule.
    
    ref class MainClientApp
    {
        // Static method Main is the entry point method.
    public:
        static void Main()
        {
            Stringer^ myStringInstance = gcnew Stringer();
            Console::WriteLine("Client code executes");
            myStringInstance->StringerMethod();
        }
    };
    
    int main()
    {
        MainClientApp::Main();
    }
    
    using System;
    using myStringer;
    
    class MainClientApp
    {
        // Static method Main is the entry point method.
        public static void Main()
        {
            Stringer myStringInstance = new Stringer();
            Console.WriteLine("Client code executes");
            myStringInstance.StringerMethod();
        }
    }
    
    Imports myStringer
    
    Class MainClientApp
        ' Static method Main is the entry point method.
        Public Shared Sub Main()
            Dim myStringInstance As New Stringer()
            Console.WriteLine("Client code executes")
            myStringInstance.StringerMethod()
        End Sub
    End Class
    
  4. 使用以下命令编译此代码:

    cl /clr:pure /FUStringer.netmodule /LN Client.cpp
    
    csc /addmodule:Stringer.netmodule /t:module Client.cs
    
    vbc /addmodule:Stringer.netmodule /t:module Client.vb
    

    指定 /t:module 该选项,因为此模块将在将来的步骤中添加到程序集。 请指定/addmodule 选项,因为Client中的代码引用了由Stringer.netmodule中的代码创建的命名空间。 编译器生成一个名为 Client.netmodule 的模块,其中包含对另一个模块 Stringer.netmodule 的引用。

    注释

    C# 和 Visual Basic 编译器支持使用以下两种不同的语法直接创建多文件程序集。

    两个编译生成了一个包含两个文件的程序集。

    cl /clr:pure /LN Stringer.cpp
    cl /clr:pure Client.cpp /link /ASSEMBLYMODULE:Stringer.netmodule
    
    csc /t:module Stringer.cs
    csc Client.cs /addmodule:Stringer.netmodule
    
    vbc /t:module Stringer.vb
    vbc Client.vb /addmodule:Stringer.netmodule
    

    一个编译创建一个包含两个文件的程序集:

    cl /clr:pure /LN Stringer.cpp
    cl /clr:pure Client.cpp /link /ASSEMBLYMODULE:Stringer.netmodule
    
    csc /out:Client.exe Client.cs /out:Stringer.netmodule Stringer.cs
    
    vbc /out:Client.exe Client.vb /out:Stringer.netmodule Stringer.vb
    
  5. 使用 程序集链接器(Al.exe) 创建包含程序集清单的输出文件。 此文件包含属于程序集的所有模块或资源的参考信息。

    在命令提示符处,键入以下命令:

    al < 模块名称><模块名称> … /main: < 方法名称>/out:<文件名>/target:<程序集文件类型>

    在此命令中, 模块名称 参数指定要包含在程序集中的每个模块的名称。 该 /main: 选项指定程序集入口点的方法名称。 该 /out: 选项指定包含程序集元数据的输出文件的名称。 该 /target: 选项指定程序集是控制台应用程序可执行文件(.exe)文件、Windows 可执行文件(.win)文件或库(.lib)文件。

    在以下示例中, Al.exe 创建一个程序集,该程序集是名为 myAssembly.exe的控制台应用程序可执行文件。 该应用程序由两个名为 Client.netmoduleStringer.netmodule 的模块组成,以及名为 myAssembly.exe的可执行文件,仅包含程序集元数据。 程序集 Main 的入口点是类 MainClientApp中位于 Client.dll中的方法。

    al Client.netmodule Stringer.netmodule /main:MainClientApp.Main /out:myAssembly.exe /target:exe
    

    可以使用 IL 反汇编程序(Ildasm.exe) 检查程序集的内容,或确定文件是程序集还是模块。

另请参阅