.NET Framework

Understanding .NET Assemblies

Introduction

 

 

In traditional Windows development, the Dynamic Link Library (or DLL) is the entity that provides reusable pieces of software. Similarly, COM provides ‘components’ in the form of DLLs and EXEs. In the .NET world it is the Assembly that provides such ‘bundled’ code reuse. Assemblies contain the code that is executed by the Common Language Runtime (CLR). Every .NET application consists of one or more assemblies. Whenever you create a console, WinForms or WebForm application or a class library you are actually creating an assembly. .NET itself exposes the majority of its functionality via assemblies. An assembly can consist of single or multiple files. Thus it can be viewed as a ‘Logical’ DLL. Each assembly must have a single entry point in the form of DllMain, WinMain or Main for the code execution. Assemblies also form a unit of deployment and versioning. .NET assemblies have certain distinct advantages over traditional DLLs or COM components (more on that later). In addition to avoid problems like DLL hell, they also make deployment a breeze.

Static and Dynamic Assemblies

 

The most common way to create an assembly is to use tools like Visual Studio.NET or command line tools (that includes command line compilers for C#, VB and AL) that ship with .NET SDK. When you compile your source code it typically creates an assembly in the form of a DLL or EXE on the disk. Such assemblies that exist physically on the disc are called as static assemblies.

.NET also allows you to create assemblies ‘on the fly’ via Reflection APIs (Reflection is the ability to obtain information about an assembly or types within that assembly like classes, interfaces, their members, methods etc. Reflection APIs are available in the System.Reflection namespace). Such in-memory assemblies, are called as dynamic assemblies. Once created and executed they can be stored to disk if required.

System Requirements

 

In the rest of this article we will be focusing mainly on the various aspects of static assemblies. To work with the examples provided in this article you would need a machine with the .NET SDK ( or Beta2) installed. For building single file assemblies (discussed later) you can also use Visual Studio.NET.

Private and Shared assemblies

 

Whenever you start a .NET application it will first look for the assemblies it requires in the installation folder. If you have more than one application using your assembly, each application will look in its own installation folder for the assembly. Thus each application has a private copy of the assembly. Such assemblies are called as private assemblies. They just have ‘ installation folder-scope ‘.

In some cases you may find it necessary for all of your applications using the assembly to share the same copy, rather than having their individual copies. In such cases you can share that assembly by hosting it in the global assembly cache (discussed in detail later). This will make the assembly available machine wide. Such assemblies are called shared assemblies. If an application cannot find an assembly it requires in the installation folder, it looks at the global assembly cache for the assembly.

You should only consider making your assemblies shared, if you have strong reasons for doing so.

 

Advantages of assemblies

 

Before going into the details of assembly structure let us quickly scan through the major advantages they offer over traditional COM components:

 

  • Assemblies help to avoid DLL Hell. DLL hell is the best-known problem with COM components. COM components are typically designed such that only a single version of the component resides on a given machine. Quite often developers fail to maintain backward compatibility with the existing code, and thus break older applications. The majority of times with .NET applications you will be dealing with private assemblies only. This means that if two applications are using different versions of an assembly, each will have its own copy thus avoiding compatibility issues. .NET also allows us to share an assembly across machines. However, such assemblies must follow certain strict rules. This makes it possible for multiple versions of the same DLL to exist on the given machine.
  • Assemblies support side by side execution: side by side execution is the ability to run multiple versions of the same assembly on a single machine. Each application is served with the version that it was built with. Shared assemblies support such side by side execution.
  • Assemblies are self-describing: COM components store details about themselves in external entities like system registry and type libraries. Whenever you start an application that uses a COM component, it will collect details about the component from the registry. Unlike COM components .NET assemblies are self-describing. They do not require any information to be stored in the system registry. All the information is contained in Metadata itself.
  • Ease of deployment: Assemblies are self describing. They do not rely on system registry for storing any information. This makes XCOPY deployment possible.
  • Easy un-installation: Since assemblies do not store any details in the system registry, the un-installation process for applications becomes very easy. Simply deleting the application folder will remove the application.

Structure of an Assembly

Before going to the details of how to build assemblies let us first understand the structure of assemblies. Assemblies consist of following elements

 

 

  • Assembly manifest (discussed in next section) which is nothing but a data structure giving details about the assembly
  • Type metadata which is nothing but the data about all the types available in the assembly
  • Microsoft Intermediate Language code (MSIL)

Single File and Multi File Assemblies

 

The elements of an assembly as mentioned above can be bundled into a single file itself. Such an assembly is called as a single file assembly. Alternatively, the entire MSIL code and associated metadata can be split into multiple files. Each individual file is called as a .NET Module. In addition to modules, assemblies can also contain other files like graphic files or resource files.

Assembly Manifest

Now that you know the basic structure of .NET assemblies, it’s time to understand something more about the assembly manifest. The assembly manifest is a data structure that stores details about an assembly. In the case of multi file assemblies assembly manifest acts as a ‘ binder ‘ for various files constituting the assembly. Note that assembly manifest is not the same as metadata. Metadata stores details about the types used in the module or assembly where as assembly manifest stores details about the assembly itself.

For single file assemblies the assembly manifest is embedded in the resulting DLL or EXE itself. Multi file assemblies however can have their manifest embedded either in a separate file or in one of the constituent files. A later section illustrates both of these techniques in detail.

Following are the important pieces of information stored by the manifest:

 

  • Assembly Name
  • Version Number
  • Operating System and processor on which the assembly is built on
  • List of all files in the assembly
  • Information about dependencies
  • Strong name information (see section on shared assemblies for more details)

Metadata

 

Metadata is defined as data about data. Each EXE or DLL contains details about the types contained within it. This data is called as metadata. Metadata contains information like:

 

  • Name and version of assembly
  • Types exposed by the assembly
  • Base classes and interfaces details
  • Security permission details
  • Attribute details (compiler and custom)

Modules

 

 

As stated earlier assemblies can consist of one or more modules. Modules form a unit of work and can be used to divide functionality into manageable pieces. They convert to MSIL, code that is executed at runtime once they are added to an assembly. Note that modules cannot be executed or used on their own. To make them useful they must be added to an assembly first. Also, one module can be added in more than one assembly. While deploying the assembly you must also deploy the constituent modules.

10/23/2007 11:03:43 PM Category .NET Assemblies

People who read this, also read...


Back