CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
}
ret
Emitting the SayHello() Method
Last but not least, let’s examine the process of emitting the SayHello() method. The first task is to obtain
a MethodBuilder type from the helloWorldClass variable. After you do this, you define the method and
obtain the underlying ILGenerator to inject the CIL instructions, like so:
// Create the SayHello method.
MethodBuilder sayHiMethod =
helloWorldClass.DefineMethod("SayHello",
MethodAttributes.Public, null, null);
methodIL = sayHiMethod.GetILGenerator();
// Write a line to the Console.
methodIL.EmitWriteLine("Hello there!");
methodIL.Emit(OpCodes.Ret);
Here you have established a public method (MethodAttributes.Public) that takes no parameters
and returns nothing (marked by the null entries contained in the DefineMethod() call). Also note the
EmitWriteLine() call. This helper member of the ILGenerator class automatically writes a line to the
standard output with minimal fuss and bother.
Using the Dynamically Generated Assembly
Now that you have the logic in place to create and save your assembly, all that’s needed is a class to
trigger the logic. To come full circle, assume your current project defines a second class named
AsmReader. The logic in Main() obtains the current AppDomain via the Thread.GetDomain() method that
will be used to host the assembly you will dynamically create. Once you have a reference, you are able to
call the CreateMyAsm() method.
To make things a bit more interesting, after the call to CreateMyAsm() returns, you will exercise some
late binding (see Chapter 15) to load your newly created assembly into memory and interact with the
members of the HelloWorld class. Update your Main() method as follows:
static void Main(string[] args)
{
Console.WriteLine("***** The Amazing Dynamic Assembly Builder App *****");
// Get the application domain for the current thread.
AppDomain curAppDomain = Thread.GetDomain();
// Create the dynamic assembly using our helper f(x).
CreateMyAsm(curAppDomain);
Console.WriteLine("-> Finished creating MyAssembly.dll.");
// Now load the new assembly from file.
Console.WriteLine("-> Loading MyAssembly.dll from file.");
Assembly a = Assembly.Load("MyAssembly");
// Get the HelloWorld type.
Type hello = a.GetType("MyAssembly.HelloWorld");
692