2.2 Creating Assemblies

To transform source code files into assemblies, you must use a language-specific .NET compiler. For C# source code files, we use the C# compiler (csc.exe) and we use the Visual Basic .NET compiler (vbc.exe) for Visual Basic .NET source files. In this section, we will demonstrate how to create single- and multifile assemblies; we do not go into detail about how to use the .NET compilers. We begin by defining two simple types, the first of which is as follows:

# C#

public class SumNumbers {
    private int o_total;

    /// <summary>
    /// Default constructor - initializes the total to zero
    /// </summary>
        public SumNumbers(  ) {
                // initialize the total
        o_total = 0;
        }

    /// <summary>
    /// Add a number to the total
    /// </summary>
    /// <param name="p_number">The number to add</param>
    public void AddNumber(int p_number) {
        o_total += p_number;
    }

    /// <summary>
    /// Get the total
    /// </summary>
    /// <returns>The total of all values presented to AddNumber</returns>
    public int GetTotal(  ) {
        return o_total;
    }
}

# Visual Basic .NET

Public Class SumNumbers
    Private o_total As Integer

    Public Sub New(  )
        ' initialize the total
        o_total = 0
    End Sub

    Public Sub AddNumber(ByVal p_number As Integer)
        o_total += p_number
    End Sub

    Public Function GetTotal(  ) As Integer
        Return o_total
    End Function
End Class

The SumNumbers class maintains a running total of integer values using the AddNumber method; the total value is obtained using the GetTotal method. The second type, SumArray, defines the static member SumArrayOfIntegers, which accepts an array of integers to be added together; this class is a consumer of SumNumbers.

# C#

public class SumArray {

    /// <summary>
    /// Static method that sums together the values in 
    /// an array of integers
    /// </summary>
    /// <param name="p_arr"></param>
    /// <returns></returns>
    public static int SumArrayOfIntegers(int[] p_arr) {
        // create a new instance of SumNumbers
        SumNumbers x_sum = new SumNumbers(  );
        // add each value in the array to the sum
        foreach (int x_int in p_arr) {
            x_sum.AddNumber(x_int);
        }
        // return the total from the sum
        return x_sum.GetTotal(  );
    }
}

# Visual Basic .NET
Public Class SumArray

    Public Shared Function SumArrayOfIntegers(ByVal p_arr(  ) As Integer) _
    As Integer
        ' create a new instance of the SumNumbers class
        Dim x_sum As SumNumbers = New SumNumbers
        ' add each value in the array to the sum
        Dim x_int As Integer
        For Each x_int In p_arr
            x_sum.AddNumber(x_int)
        Next
        ' return the total from the sum
        Return x_sum.GetTotal(  )
    End Function
End Class

We will save the SumNumbers type in a file named SumNumbers.cs (C#)/SumNumbers.vb (Visual Basic .NET) and the SumArray type in a file named SumArray.cs (C#)/SumArray.vb (Visual Basic .NET).

2.2.1 Creating a Single-File Assembly

This is the default assembly type created by the C# and Visual Basic .NET compilers. The assembly metadata and the MSIL statements are included in a single file. The following statements demonstrate how we create a single-file library assembly from our source files:

# C#

csc /out:SingleFileAssembly.dll /target:library SumNumbers.cs SumArray.cs

# Visual Basic .NET

vbc /out:SingleFileAssembly.dll /target:library SumNumbers.vb SumArray.vb

These statements create a single-file assembly named SingleFileAssembly.dll, which contains the compiled SumNumbers and SumArray types; the /out argument allows you to specify the name of the created file, while the /target option allows you to choose between application and library assemblies; consult the .NET documentation for full details of the compiler options.

2.2.2 Creating a Multifile Assembly

Creating a multifile assembly is more complicated than creating a single-file assembly but does provide additional flexibility; in this section, we demonstrate how to create an assembly that contains modules written in different .NET languages. We start by compiling our C# implementation of the SumNumber type into its own module:

csc /out:SumNumbers.netmodule /target:module SumNumbers.cs

This command creates a new module called SumNumbers.netmodule. The "netmodule" suffix is the standard for module files, in the same way that "dll" is for library files. We will now compile our Visual Basic .NET implementation of the SumArray type into a module. The SumArray class depends on the functionality of the SumNumbers class, and we reference the SumNumbers.netmodule file with the /addmodule argument:

vbc /out:SumArray.netmodule /target:module /addmodule:SumNumbers.netmodule \
  SumArray.vb

We have now created two modulesSumNumbers.netmodule is creating from a C# class, while SumArray.netmodule is created from a Visual Basic .NET class. .NET modules can contain more than one type, although each type must be defined in the same languagewe have created modules containing only one type in order to present a simple and clear example.

We can now create a multifile assembly that contains our modules by using the Assembly Linker tool (al.exe). The following command creates a library assembly called MultiFileAssembly.dll:

al /out:MultiFileAssembly.dll /target:library SumNumbers.netmodule SumArray.netmodule

The Assembly Linker creates the DLL file, which contains only the assembly metadata and references to the module files, each of which includes one of our example classes.

A multifile assembly consists of the metadata file (the .dll or .exe) and all of the modules you specified to the Assembly Linker. When distributing a multifile assembly, you must include all of the files with a netmodule suffix as well as the metadata file.



    Part V: API Quick Reference