In addition to execution instructions, CIL code includes metadata about the types and files included in a program. The metadata includes the following:
The metadata is not a cursory, nonessential add-on to the CIL. Instead, it forms a core part of the CLI implementation. It provides the representation and the behavior information about a type and includes location information about which assembly contains a particular type definition. It serves a key role in saving data from the compiler and making it accessible at execution time to debuggers and the runtime. This data is not only available in the CIL code, but also is accessible during machine code execution so that the runtime can continue to make any necessary type checks.
Metadata provides a mechanism for the runtime to handle a mixture of native and managed code execution. Also, it increases code and execution robustness because it smoothes the migration from one library version to the next, replacing compile-time-defined binding with a load-time implementation.
All header information about a library and its dependencies is in a portion of the metadata known as the manifest. As a result, the manifest portion of the metadata enables developers to determine a module's dependencies, including information about particular versions of the dependencies and signatures of who created the module. At execution time, the runtime uses the manifest to determine what dependent libraries to load, whether the libraries or main program have been tampered with, and whether assemblies are missing.
The metadata also contains custom attributes that may decorate the code. Attributes provide additional metadata about CIL instructions that are accessible via the program at execution time.
Metadata is available at execution time by a mechanism known as reflection. With reflection, it is possible to look up a type or its member at execution time and then invoke that member or determine whether a construct is decorated with a particular attribute. This provides late binding, determining what code to execute at execution time rather than at compile time. Reflection can even be used for generating documentation by iterating through metadata and copying it into a help document of some kind (see Chapter 14).