You provide
the compiler with your assembly information in an assembly
information file (usually called in a C# project,
AssemblyInfo.cs
). The assembly information file
is compiled with the rest of the project’s source files. The
information in the file is in the form of assembly
attributes
—
directives to the
compiler on the information to embed in the assembly. Example C-2
shows a typical set of assembly attributes.
Example C-2. The assembly information file includes a variety of assembly attributes
[assembly: AssemblyTitle("MyAssembly")] [assembly: AssemblyDescription("Assembly containing demo .NET components")] [assembly: AssemblyCompany("My Product")] [assembly: AssemblyCopyright("(c) 2001 My Company ")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("en-US")] [assembly: AssemblyVersion("1.0.*")]
Assemblies can be
private or shared. A private assembly resides in
the same directory of the application that uses it (or in its path).
A shared assembly is in a known location, called
the global assembly cache (GAC), mentioned in
Chapter 10
Chapter 10. To add an
assembly to the GAC, use either the .NET administration tool or the
GACUtil
command-line utility. Once in the GAC,
the assembly can be accessed by multiple applications, both managed
and unmanaged.
To avoid conflicts in the GAC between different assemblies that have
the same name, a shared assembly must have a strong
name. The strong name authenticates the assembly’s
origin and identity and cannot be generated by a party other than the
original publisher. The strong name allows any client of the assembly
(usually the assembly loader) to deterministically verify that the
assembly was not tampered with. Assigning a strong name to an
assembly is also known as signing
the assembly.
To assign a strong name to your assembly, you first need to generate
private or public encryption keys. You can generate the pair using
the SN.exe
command-line utility:
SN.exe -k MyAssembly.snk
Future versions of Visual Studio.NET may enable you to generate keys
from within the visual environment. The -k
switch instructs SN to generate a new pair of keys and store them in
the filename specified. The convention used for the filename is the
assembly name with the strong name key (snk)
extension, but it can actually be any name and extension you like.
You then add the snk
file to the
assembly’s information file, using the
AssemblyKeyFile
assembly
attribute:
[assembly:AssemblyKeyFile("MyAssembly.snk")]
In addition to a version number and a strong name, a shared assembly
must have a namespace and locale identifier that
identify the human language used in its user interface. In Example C-2 the locale is specified by the
AssemblyCulture
assembly attribute.
Each
assembly must contain metadata. The
metadata is the .NET equivalent of COM’s type libraries, except
the metadata is more like a type library on steroids. The metadata
contains descriptions of all the types defined in the assembly, such
as interfaces, classes and their base classes, method signatures,
properties, events, member variables, and custom attributes. The
metadata is generated automatically by the compiler when it compiles
the source files of your project. You can view the metadata of your
assembly using the ILDASM
utility.
While the metadata describes the types in your assembly, the manifest describes the assembly itself. The manifest contains the assembly version information, the locale information, and the assembly’s strong name. The manifest also contains the visibility of the assembly’s types—which types are public (can be accessed by other assemblies) and which types are internal (can only be accessed from within the assembly). Finally, the manifest contains the security permission checks to run on behalf of the assembly.
Like the metadata, the manifest is generated automatically by the compiler during assembly compilation. You can view the manifest of your assembly using the ILDASM utility.
Because every assembly must contain the manifest and metadata (and usually IL code and resources), a single DLL or EXE assembly contains all of them in one file. However, the only requirement of a multifile assembly is that a file containing IL must also contain metadata describing it. Such a file is called a module. A multifile assembly must still have one DLL file that contains the manifest. Figure C-1 shows a few possibilities for composing assemblies.
As you can see, you can compose the assembly in almost any way and use compiler switches to bind all your files together. In practice, most assemblies contain just one DLL (the Visual Studio.NET IDE provides only this option) and are composed of one file.