Meta-Programming


Meta-Programming

The ability to dynamically create new types at runtime is known as meta-programming. The CLR provides this capability through Reflection.Emit . Creating dynamic types is a fundamental facility in the remoting services. For example, COM and CORBA can produce code for proxy objects at IDL compile time. This code is then linked with the client and server programs. With the CLR's remoting services, the runtime environment dynamically creates proxy objects whenever the need arises. This approach eliminates the problem of locating and loading the DLL that contains the proxy code at runtime.

Figure 3.7 shows some of the classes involved in providing meta-programming facilities. The diagram is similar to Figure 3.1, which depicts the reflection class hierarchy. The Builder classes provide the functionality needed to create a new type or member at runtime.

Figure 3.7. Meta-programming classes

graphics/03fig07.gif

Listing 3.9 demonstrates how to dynamically create a new type and then persist it to disk. It loads the assembly from disk, creates an instance of the new type, and calls a method on the new type. As types are located in modules and modules are located within assemblies, it follows that the creation of a new type requires the creation of a module and an assembly.

Listing 3.9 Using meta-programming
 using System.Reflection.Emit; using System.Threading; public class DynamicType {   private static void CreateMethodBody(MethodBuilder m)   {     ILGenerator il = m.GetILGenerator();     il.EmitWriteLine("Hello World! from a new type");     il.Emit(OpCodes.Ret);   }   public static int Main(String[] args)   {     AssemblyName an = new AssemblyName();     an.Name = "MyAssembly";     AssemblyBuilder ab =             Thread.GetDomain().DefineDynamicAssembly(an,                        AssemblyBuilderAccess.RunAndSave);     ModuleBuilder mb = ab.DefineDynamicModule("MyModule",                                  "MyAssembly.dll", true);     TypeBuilder tb = mb.DefineType ("Sample.NewType",                                    TypeAttributes.Public);     MethodBuilder m = tb.DefineMethod("MyMethod",                                  MethodAttributes.Public,                                  null, null);     CreateMethodBody(m);     tb.CreateType();     ab.Save("MyAssembly.dll");     Type t = Type.GetType("Sample.NewType,MyAssembly",                           true);     Object o = Activator.CreateInstance(t);     MethodInfo myMethod = t.GetMethod("MyMethod");     myMethod.Invoke(o,null);     myMethod = t.GetMethod("ToString");     Console.WriteLine(myMethod.Invoke(o,null));     return 0;   } } 

Listing 3.9 produces the following output:

 Hello World! from a new type  Sample.NewType 

Of course, running this program creates an assembly in the current directory. You can use ILDASM to display its contents, just to show it is a valid CLR file (see Figure 3.8).

Figure 3.8. Output of Listing 3.9: an assembly in the current directory

graphics/03fig08.gif

Also using ILDASM, you can show the emitted IL for MyMethod (see Figure 3.9).

Figure 3.9. IL for MyMethod

graphics/03fig09.gif

Meta-programming is somewhat beyond the scope of this book, so it will not be covered in detail here. This short introduction should whet your appetite to learn more, however.



Programming in the .NET Environment
Programming in the .NET Environment
ISBN: 0201770180
EAN: 2147483647
Year: 2002
Pages: 146

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net