Free mag vol1 | Page 749

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