An assembly is a collection of one or more files containing type definitions and resource files. One of the assembly’s files is chosen to hold a manifest. The manifest is another set of metadata tables that basically contain the names of the files that are part of the assembly. They also describe the assembly’s version, culture, publisher, publicly exported types, and all of the files that comprise the assembly.
The CLR operates on assemblies; that is, the CLR always loads the file that contains the manifest metadata tables first and then uses the manifest to get the names of the other files that are in the assembly. Here are some characteristics of assemblies that you should remember:
- An assembly defines the reusable types.
- An assembly is marked with a version number.
- An assembly can have security information associated with it.
To package, version, secure, and use types, you must place them in modules that are part of an assembly. In most cases, an assembly consists of a single file, as the preceding Program.exe example does. However, an assembly can also consist of multiple files: some PE files with metadata and some resource files such as .gif or .jpg files. It might help you to think of an assembly as a logical EXE or a DLL.
three reasons to use multifile assemblies:
- You can partition your types among separate files, allowing for files to be incrementally downloaded as described in the Internet download scenario. Partitioning the types into separate files also allows for partial or piecemeal packaging and deployment for applications you purchase and install.
- You can add resource or data files to your assembly. For example, you could have a type that calculates some insurance information. This type might require access to some actuarial tables to make its computations. Instead of embedding the actuarial tables in your source code, you could use a tool (such as the Assembly Linker, AL.exe, discussed later) so that the data file is considered to be part of the assembly. By the way, this data file can be in any format—a text file, a Microsoft Excel spreadsheet, a Microsoft Word table, or whatever you like—as long as your application knows how to parse the file’s contents.
- You can create assemblies consisting of types implemented in different programming languages. For example, you can implement some types in C#, some types in Microsoft Visual Basic, and other types in other languages. When you compile the types written with C# source code, the compiler produces a module. When you compile other types written with Visual Basic source code, the compiler produces a separate module. You can then use a tool to combine all of these modules into a single assembly. To developers using the assembly, the assembly appears to contain just a bunch of types; developers won’t even know that different programming languages were used. By the way, if you prefer, you can run ILDasm.exe on each of the modules to obtain an IL source code file. Then you can run ILAsm.exe and pass it all of the IL source code files. ILAsm.exe will produce a single file containing all of the types. This technique requires your source code compiler to produce IL-only code.
The assembly file that contains the manifest also has an AssemblyRef table in it. This table contains an entry for all of the assemblies referenced by all of the assembly’s files. This allows tools to open an assembly’s manifest and see its set of referenced assemblies without having to open the assembly’s other files. Again, the entries in the AssemblyRef table exist to make an assembly self-describing.
1 AssemblyRef #1 (23000001) 2 ------------------------------------------------------- 3 Token: 0x23000001 4 Public Key or Token: b7 7a 5c 56 19 34 e0 89 5 Name: mscorlib 6 Version: 4.0.0.0 7 Major Version: 0x00000004 8 Minor Version: 0x00000000 9 Build Number: 0x00000000 10 Revision Number: 0x00000000 11 Locale: <null> 12 HashValue Blob: 13 Flags: [none] (00000000) 14 15 16 AssemblyRef #2 (23000002) 17 ------------------------------------------------------- 18 Token: 0x23000002 19 Public Key or Token: 20 Name: A 21 Version: 1.0.0.0 22 Major Version: 0x00000001 23 Minor Version: 0x00000000 24 Build Number: 0x00000000 25 Revision Number: 0x00000000 26 Locale: <null> 27 HashValue Blob: 28 Flags: [none] (00000000)
Building an Assembly That References a Strongly Named Assembly
if you specify a file name without a path, CSC.exe attempts to find the assembly by looking in the following directories (in order of their presentation here):
- Working directory.
- The directory that contains the CSC.exe file itself. This directory also contains the CLR DLLs.
- Any directories specified using the /lib compiler switch.
- Any directories specified using the LIB environment variable.
when you install the .NET Framework, two copies of Microsoft’s assembly files are actually installed. One set is installed into the compiler/CLR directory, and another set is installed into a GAC subdirectory. The files in the compiler/CLR directory exist so that you can easily build your assembly, whereas the copies in the GAC exist so that they can be loaded at run time.