The best way to describe an assembly is that it's the fundamental unit of deployable code in the .NET Framework. That may sound awkward , but it's still the best way to describe assemblies. The .EXE and .DLL files you create are assemblies, and each assembly is a collection of files held internally and appearing to the users to be a single file. The term assembly was introduced because you can produce deployable code in both EXE and DLL format, and the term assembly covers them both.
Assemblies were also designed to alleviate "DLL Hell," which occurs when a new application loads a new version of a DLL file, overwriting the previous version. Such an action can break earlier applications that relied on the original DLL. Because assemblies maintain version information that can be accessed by the CLR, different versions of an assembly can co-exist side by side without overwriting any resources like DLL files.
Assemblies can contain many files inside them, including resources like image files. The assembly's code is stored in code modules , in MSIL format. Although the assemblies you can create with C# in the IDE can only contain a single module, we'll see how to build multi-module assemblies in this chapter (the assemblies you create using C++, not C#, in the IDE can actually produce multi-module assemblies).
We're also going to look at the internal structure of assemblies in this chapter. In fact, to describe their own internal structure, assemblies include metadata in a manifest , which describes the assembly and its contents. The manifest describes the types and methods in the assembly, and we're going to get some first-hand knowledge of that in this chapter. The manifest holds the assembly's name, version, a list of the types and the resources in the assembly, and a map connecting the name of a type to its code. There's also a list of the assemblies this assembly references, including the name of the referenced assemblies, their version numbers , their cultures (a culture refers to data such as language and text display details), and their creators . Each assembly also has a version number, which labels not only the assembly, but everything in the assembly as well. In other words, all the types in an assembly change version numbers when you change the assembly's version number. Security permissions, which we'll take a look at later in the chapter, are granted on the assembly level.
Internally, assemblies can also have onebut only oneentry point, which calling code will call first. These entry points are WinMain (for Windows EXEs), Main (for standard code like console application EXEs), or DLLMain (for DLLs, usually called if you want to initialize some aspect of the DLL). Assemblies also provide security boundariesan assembly is the scope boundary for the types it contains and types that cannot cross assembly boundaries. You cannot have a type definition span two assemblies, but you can use a reference to a type in another assembly.
That's all the overview we need for the moment; let's get to some code. In our first example, we'll create an assembly and then take a look at what's inside.