Code reusability has always been one of the major concerns for software developers. You do not ever want to write a similar code for two business problems. You would rather like to write the solution once and reuse it whenever and wherever required. This requirement of code reusability gave rise to the concept of creating assemblies and using them in different applications by adding a reference to the same. We will get to know more about it as we have a closer look at assemblies.
An assembly is a block of compiled code which is reusable, versionable, and self-describing. It is an assembly that takes the form of an executable (.exe) file or dynamic link library (.dll). When we build our application, all the .cs files are put together to form an assembly. This assembly (.exe or .dll) can be found on the disk in the bin/debug folder located inside the project folder. This code can be executed under the supervision of Common Language Runtime. Unlike the .exe assemblies, the .dll assemblies are non-executable, but can be loaded and used by another program.
An assembly contains information about how every element is related to each other. This information is the assembly metadata stored in the assembly manifest. The assembly manifest contains:
- the assembly’s identity defined by its Name and Version
- a file describing all the elements that forms the assembly. It can be some .cs files, Readme files or even some other assemblies created by you that your current assembly relies on
- an assembly reference list which is a list of all external dependencies (that may have been created by others) our application needs.
Depending upon the business problem, our application may require assemblies that are self created, provided by a third party or the assemblies that are provided by the .net framework. One of the commonly used .net provided assemblies is mscorlib.dll. It is this assembly that contains the classes like Console, DateTime, String and others.
When we create any application with Visual Studio, depending on the type of our application, references to some assemblies are added by default. All the assembly references added by Visual Studio may not be useful for the application. But, this may not even add any performance issue as .net loads an assembly only when the application uses a class from the respective assembly.
When our application is in execution and it requires a class or a type to be found from a different assembly, we must have that assembly loaded into the memory. One appropriate approach to do so is to add a reference to that assembly. I would recommend How to: Add or Remove References By Using the Reference Manager to get a better understanding about adding and removing references.
Global Assembly Cache (GAC)
As we talk about references, it is important to note that our assembly references contain reference to both private and global objects. Private objects must be in a directory either at the same level as or below the directory in which your application is installed. Whereas the global objects reside in the global assembly cache. Assemblies stored in the global assembly cache are available to all the .net applications that run on the machine. This is the reason why important core libraries like mscorlib live inside the global assembly cache, so that only a single copy of the library is available for the entire machine.
On a windows machine, if you wish to have a look at what all assemblies are available, go to your windows drive (e.g. C:\>) and underneath your Windows directory, you will find the assembly directory. Further inside the assembly directory you will find the sub-directories named as GAC, GAC_32, GAC_64 and GAC_MSIL. Kindly refer the image below.
Now as we know that when we build our application its assembly is generated either as .exe or .dll. We can always choose what shall be the extension of our assembly, as per our requirement. Following are the steps to achieve the same:
- Open the project Properties in the Solution Explorer of Visual Studio and go-to Application tab
- Assembly Name: name of the assembly that will be created (default value – project name)
- Output Type: decides the extension of the output file (.exe or .dll)
- value as Class Library – generates an assembly with .dll extension. This assembly is a non-executable, but can be referenced by other applications
- value as Windows/Console Application – generates an assembly with .exe extension. This assembly can be executed directly, but can not be referenced by other application
- Assembly Information: helps you to add more information, like version, description, company, about the assembly. Once you save the information, an AssemblyInfo.cs is added into your project file.
A comparison between .exe and .dll
The basic difference between the two types is that the .exe is an executable form of an assembly whereas an assembly takes the form of a .dll when its code is to be reused or referenced by some other applications. A .dll can not be executed as a standalone application. This derives the fact that, while a .exe executes in its own address space, a .dll always requires a host to load and execute it. Also, the address space is shared between the two. Secondly, the entry point for an executable is the main thread (commonly known as the main method), whereas a library (.dll) does not have a main method and is executed in the context of the running process.
To conclude, we shall always create a .dll assembly when we want our code to be reused by other applications as a library reference. And we shall create an executable when we want to run our application as a standalone application.
I hope this helps you get a better understanding about the assemblies and how they make your code reusable. It’s always great to have feedback from the readers. Your valuable feedback, question, or comments about this article are always welcome.