Many developers assume that an assembly is just a simple DLL or an EXE file; simply the output produced by compilation. On the surface, this appears to be true, but there is a lot more to an assembly than just storing the compiled code.
Inside the assembly, there is far more than just the compiled code. As mentioned earlier, when the compiler creates an assembly, it stores compiled code as well as metadata.
Figure 12.1 illustrates the contents of a .NET assembly. There is a manifest, a list of the types contained within the assembly, assembly-level metadata, and finally the MSIL code created by the compiler.
Figure 12.1. Contents of a .NET assembly.
When you build an assembly (discussed in the next section), the compiler does a lot of things for you. It stores the list of types contained in that assembly, a list of dependencies (referenced assemblies that are required for the assembly to function properly), resources such as multilingual strings and images, and finally the compiled MSIL code.
An assembly can actually be a multifile assembly. In a multifile assembly, you can separate blocks of MSIL code and types into multiple modules. When you create the assembly, you then link the multiple modules via the assembly manifest of the primary assembly. This allows you to create a single logical assembly that can actually contain 20 different files. The beauty of this is that when the CLR attempts to load the primary assembly, it will automatically load all of the multiple files that make up the assembly. If one of the files is missing, the assembly will not load.
Introducing the Assembly Manifest
The assembly manifest is a collection of metadata that describes the contents of the assembly. It contains metadata about the assembly itself such as the version number, the public key, and so on. In addition, it contains a list of dependencies. These dependencies are checked when the assembly is loaded. If one of the dependencies fails to load, so too does the assembly. The manifest also contains a list of the resources used by the assembly.
To take a look at what the CLR sees when it loads an assembly manifest, you can use the ILDASM.EXE tool that comes with the .NET Framework SDK. To use this, you can open up a Visual Studio 2005 Command Prompt from the Visual Studio Tools group on your Start menu. Then type ILDASM and a new window will appear. Select File, then Open, and then browse to \Windows\Microsoft.NET\Framework\v2.0.50727\ and select System.Data.dll. You'll see a plethora of information about the types, resources, and metadata contained within the assembly appear in a useful tree structure. Double-click the MANIFEST node and you will see a window that looks like the one shown in Figure 12.2.
Figure 12.2. An assembly manifest, as seen by the ILDASM tool.
You don't need to understand the language of the statements contained in the manifest, but it should be pretty easy to recognize a lot of the elements being discussed here. When browsing through the manifest, you can see the list of dependencies when you see the .assembly extern statements. The list of resources contained within the assembly is also stored within the manifest.