 |
Introduction
In my previous article on Assembly and Module,
I gave you a brief introduction on the features and differences between the two
concepts. In this article on the request of why_zjs
- China (I don't have your name pal! ) I will explore more
into the actual part of compiling Assemblies and Modules. I will
also use the tool ILDASM to show you the actual difference between
the two.
ILDASM - Tool
ILDASM in short stands for IL (Microsoft Intermediate Language) Disassembler.
This is a very powerful tool which makes use of Reflection
internally to show the different classes and class members contained
within an assembly or a module. ILDASM also shows the Metadata
contained within the assembly/module. It is very useful in
situations you have the assembly but don't know its contents, just
use ILDASM to discover the different classes their access modifiers, different
class members, their parameters and return types.
To run the ILDASM tool go to Start -> Run within the dialog type ILDASM and press Enter.
To view the contents of assembly/module choose the assembly/module from the File
->Open dialog of ILDASM. Note: ILDASM can only be used to
view the contents of a .NET PE (Exe/Dll) file, it cannot be used to
view the contents of a regular PE file.
Example 1: Module
Let's get started...
To start up, I have written a small class (given below) and saved it as FirstClass.cs. This class is a public class with
just one method.
using System;
public class FirstClass
{
public void PrintMessage()
{
Console.WriteLine("I am First Class");
}
} |
Now we first compile this class into a
Module, the compilation string will be:
csc /t:module FirstClass.cs
This will create a FirstClass.netmodule file in the directory you
ran the compiler.
Note: We use the /t:module compiler switch to
compile a module.
Now let's examine this module, fire up the ILDASM tool, and select the FirstClass.netmodule
file from File -> Open"dialog of the ILDASM tool. There is one hitch here although, ILDASM does not
shown the *.netmodule extension in the Open File dialon.
To workaround this, select Any type (*.*)" from the Types of Files
dropdown in the Open File
Dialog and then select the module.
Once you have the right file selected you should
be able to see something like below
Figure 1: ILDASM: FirstClass Module
If you remember, in the last article I had stated that modules don't
have an Assembly Manifest but in ILDASM (the above figure too) shows that
our module has a Manifest. How is this possible?? I would like you to
mark my words carefully, I said, "modules don't have Assembly Manifest" that does not mean
that modules don't have a manifest! There's a big difference between
a Manifest and an Assembly Manifest as we shall see below.
So what does the the Manifest of a module contain? The easiest way is to Double-Click
on the Manifest item in ILDASM and find out yourself!
Figure 2: ILDASM: Manifest of the FirstClass Module
Your module manifest window should look like figure 2. I know
that more than half of it won't make any sense to you (it doesn't make any sense
to me either!! ), but we can notice a few important things. Firstly, .assembly extern mscorlib
section defines, that this module is using some classes exported from the
assembly mscorlib (mscorlib.dll). Can you find out which classes from the mscorlib assembly have been used in our
example????
1) System.Console - class is placed within the mscorlib assembly
and
2) System.Object - why? All .NET classes derive for System.Object,
remember !!!
Also within the extern section we find .ver 1:0:3300:0, this is the exact
version of the mscorlib assembly against which
our class has been compiled, from this we can make out how the versioning
policy of the .NET Framework works. Even if in the future
another build of the mscorlib assembly is installed, still the .NET runtime will
load the correct version of the assembly i.e. 1:0:3300:0 version
while running this module. This hard-coding of the assembly
version within the Manifest rids the .NET Platform the buggy Windows
Registry, since now the .NET PE files are self-describing
and contain all the information required by the runtime in the form
of Metadata stored in its manifest.
Example 2: Assembly
In this example we use the same FirstClass class but this time we
compile it as an assembly. So now our compilation string changes to:
csc /t:library FirstClass.cs
The above will compile a library Dll called FirstClass.dll in the
directory you ran the command.
Again we fire up the ILDASM tool to examine this assembly (I hope by
now you know how to load the library dll into ILDASM??). On first
looks it might seem the same as the module definition, but the real
magic is within the Manifest, so without any further delay
double-click the Manifest item within the ILDASM tool.
Figure 3: ILDASM: Manifest of FirstClass Assembly
The above snap-shot of the Manifest makes
the difference between Assemblies and Modules clear! As marked in
green above, the assembly contains an 'Assembly Manifest'. This
Assembly Manifest contains the Hash of the class and the Version
of the assembly. Since I have not specified any versioning information during
compilation a default version of 0:0:0:0 is
used by the compiler. It's this Assembly Manifest used by the .NET
Runtime to determine the version other details of the
Assembly.
As I have mentioned earlier .NET Platform follows strict versioning,
if the Assembly Manifest is missing (like in the case of Modules)
the runtime cannot know which version of the file to load, hence it
can't proceed any further! Hence its said that you cannot use
Modules directly and they can only be accessed via assemblies.Example 3: Consuming a Module
Since modules can't be used directly you have to create an assembly
that references the module. Let's take one more example to learn to consume
Modules. Write the below code into Notepad and save it as MainClient.cs.
public class MainClient
{
public static void Main()
{
FirstClass fc = new FirstClass();
fc.PrintMessage();
}
} |
Firstly, we will compile the application referencing the
module. Compile the above file with the compilation string:
csc /addmodule:FirstClass.netmodule MainClient.cs
This will compile a Console Application MainClient.exe.
Note that the compiler option /addmodule is used to reference a
module.
Go to the
command prompt, navigate to the folder that hosts the application
and run it, you should see the output as
I am First Class.
To understand what happens internally, open the MainClient.exe
file in ILDASM and Double-Click the Manifest item.
Figure 4: ILDASM: Manifest of MainClass
As its clear from the above screen-shot,
that when we reference a Module, then the Assembly Manifest
contains extra metadata for the referenced module as well as for the classes
contained within it. Remember that we have only referenced the Module within our
assembly, hence while distributing our application we have to copy the FirstClass.netmodule too, or the
application won't run! In this example we built an application in which we have
one Assembly and one Module, since the Assembly has Metadata not only of itself
but also of the Module/s it references it can be said that Assemblies can span Multiple Physical
Files.
Conclusion
From the above example it is clear that both Modules and
Assemblies have Manifests. This Manifest contains Metadata
information of the Module/Assembly as well as it contains detailed
Metadata of other assemblies/modules references (exported). It's the
Assembly Manifest which differentiates between an Assembly and a
Module.
The Assembly Manifest contains important information required by
the .NET Runtime to execute the IL code within the PE file successfully!
We also saw how Versioning support has been built into the .NET PE
files. Some curious learners among you might have also noticed that
Referencing Assemblies/Modules only adds the reference to the
assembly/module in your code and the code in the external file does
not get imported into your code. This is the reason that you have to
supply all the Assemblies/Modules you use in your Application along
with the Assembly that builds you application.
Now, using ILDASM isn't so hard is it? Play with it and you will
learn a lot of things :) |
 |