|
Assemblies Background
The C# Column
Dynamic
Link Libraries was a significant step in the quest for code reuse.
COM technology used the good things in DLLs to take the reuse to
its next logical conclusion language independent reuse. However,
over the years as numerous components got created, the shortfalls
of COM technology regarding deployment and maintenance came to the
fore. Assemblies is Microsofts .NET-based answer
to these problems.
Background
The earliest form of reuse was in the form of Static Libraries. These libraries
contained object code of functions. During linking the object code of the library
functions (usually stored in .lib file(s)) was linked with the object code of
the program calling those functions to form an executable file. The linking
phase used to precede execution. This way the library functions could be reused
by different applications calling them. This however led to wastage of storage
space as the object code from the function library used to get replicated into
every application using it.
In multitasking environments if two applications were running in memory each
calling the same library function then two copies of the same function would
be running in two different processes. This led to wastage of precious memory
space. Also, if a bug was found in the library functions the library as well
as the client program using it had to be re-compiled and re-distributed. A recipe
for disaster for sure!
To avoid the wastage of memory and disk space Microsoft suggested the concept
of Dynamically Linked Libraries (DLLs). Functions from these libraries never
became part of an application trying to call them. Instead they used to get
linked with the applications calling them at runtime. Moreover, multiple applications
calling them used to share the same copy of the library function present in
memory. A developer could simply place the DLL in Windows directory, Windows\System
directory or in the same directory as the EXE file using that DLL and then rely
on the operating system to do the linking at run-time.
This to begin with was a welcome change from the static libraries of the past.
However, as programmers started building DLLs, they realized that the
concept though apparently promising, is infested with several problems like
tedious cross-language usage, DLL Hell (versioning problem) and lack of location
transparency.
Component Object Model
Component software was a paradigm for designing and implementing an application
by putting together independent pieces of software instead of writing one big
monolithic application. COM components had unique characteristics that made
them very attractive as building blocks for larger applications. They could
be distributed either as DLLs or as EXEs. Clients could bind to the components
at runtime and didnt have to be recompiled due to any upgrades to the
components. The components could be transparently relocated on a remote computer
without affecting the clients i.e. local and remote components were treated
in the same manner. This made distributed computing very easy. The components
could be written in any programming language as long as they followed a standard
memory layout prescribed by the COM specifications. Additionally COM was object-oriented.
COM components along with COM interfaces supported the concept of encapsulation
and polymorphism.
With COM it became easy to write a component in any of the languages supporting
COM and to call it from other languages. But this ease was topped up with complexity.
COM was difficult to learn. Moreover storing information about all components
in the registry made the process of installing software quite complex.
If an application was to use a COM component, it needed the methods and properties
stored in COM component, the type library information and the registry entry
of the component. If for any reason any of these was unavailable, the component
was rendered unusable.
.NET overcomes all these problem using Assemblies.
What is an Assembly?
Any .NET code (be it an EXE or a DLL) on compilation is stored as an Assembly.
The entire .NET code (any language) gets converted in the form of IL code. Hence
an assembly is .NETs approach to code reuse.
In addition to the IL code, an assembly also contains Assembly Metadata, Type
metadata and Resources. Assemblies are hence self-describing. Its no longer
necessary to pay attention to registry keys or type library. Assemblies include
metadata that describe the assembly. Following figure shows the composition
of an assembly created after compiling a DLL called myassembly.dll.
The Assembly Metadata is also called the Manifest. A manifest is a data structure
that serves the same purpose as the type library and associated registry entries
do, for a COM component. Manifest contains more information than a type library.
The Type Metadata includes the types (classes, methods and properties) exported
from the assembly.
Some of the salient features of assemblies are as follows:
Assemblies can be loaded using the side-by-side technique. This means two different
versions of the same assembly can be used inside a single process.
Assemblies support Zero-impact installation. Installation can be as easy as
copying the files that belong to an assembly.
An assembly may represent one file or might be spread across several files.
Structure of Manifest
Manifest serves as a very important entity. Let us now understand what the manifest
looks like. We know that the assembly is made up of metadata, IL code and resources.
Metadata consists of type metadata and assembly metadata. The assembly metadata
describes the assembly and is called the Manifest. A manifest contains:
The identity of the assembly, consisting of its name, version and culture.
An assembly has a four part version number e.g. 1.0.1.1. The parts are
<Major> . <Minor> . <Build> . <Revision>
The use of these numbers is dependent on the configuration of our application.
If the new version created is compatible with the older version we must not
change the major or minor numbers. On the other hand if the versions are incompatible
we must change the major and minor numbers. The build number is the number of
days since Jan-1, 2000, and revision is the number of seconds since midnight
local time.
Names of all the files in the assembly.
Whether all the types defined in the assembly are visible to other assemblies
or private to one.
A hash of all files in the assembly.
Details of any security permissions that clients need to have in order to be
able to run the assembly.
Type metadata consists of metadata describing the exported
types and methods. We can view the assembly and manifest using a
tool called ILDASM.
 |
Yashavant Kanetkar, one of
the first Express Computer columnists, is an established software
expert, speaker and author with several best-sellers to his
credit, including titles like “Let Us C” and the “Fundas” series.
Contact him at kanetkar@dcubesoft.com |
|