What's Inside of an Assembly?
An assembly's EXE or DLL file is a standard "Portable Execution" (PE) file, the same file format used for non-.NET executables and code libraries (pretty much any Windows EXE or DLL file). What makes .NET PE files different is all the extra stuff found inside. As a general word, "assembly" indicates a gathering together of various parts into a single unit. In a .NET assembly, these "various parts" are specifically designed for use with .NET. A .NET PE file contains three main parts.
In multi-file assemblies, the manifest-specific elements only appear in the "main" file of the assembly.
The manifest is a subset of the metadata within your assembly. I hate to say that it's the most important part of the metadatabut it is. The manifest is the public expression of your assembly, and the only way that .NET knows whether it is legit. It's sort of like the "Nutrition Facts" label put on American food packaging (see Figure 5-2).
Figure 5-2. Is that really good for me?
When you look at the food label, you know what the food package containsalthough no one really knows what riboflavin is. When you look at the manifest for an assembly, you know at a glance what the assembly contains, and what requirements it has before it can be loaded and run.
Even before .NET burst onto the scene, executables and libraries already contained some "metadata," such as the version number of the file. But this data wasn't used to manage access between software components, nor was it organized in a generic and extensible way. The metadata in .NET embodies all of these attributes.
The presence of both the MSIL and metadata in each assembly make these files very readable and understandable. With the right tools, even I seem to understand them. And if I can, then anyone can, which leads to a big problem. Companies invest a lot of time and money in their software development efforts, and they don't want any rinky-dink two-bit startup reverse engineering their code and getting all of their algorithmic secrets. To prevent this casual reading of any .NET application, Microsoft and other third parties include obfuscators, software programs that scramble the contents of an assembly just enough so that it's hard for humans to understand, but not for the .NET Framework. I'll talk more about obfuscation in Chapter 21, "Licensing Your Application."
It may be a bad thing for people to access the content of an assembly, but it's great when the code in an assembly can access itself. .NET includes a feature called reflection that lets you examine the contents of an assembly. You generally use this feature to access metadata in your own assembly, but it also works with any available assembly. All reflection-related code appears in the System.Reflection namespace.
Through reflection, you can extract pretty much anything stored in the metadata of an assembly, including details on all types, their members, and even the parameters included with function members. This is why obfuscation is so important to vendors; between the compiled MSIL and the metadata, you can virtually regenerate the entire source code for an application from just its executable. The source code would be in MSIL, but it wouldn't be that tough for someone to massage much of it back into Visual Basic or C#.