CHAPTER 18 UNDERSTANDING CIL AND THE ROLE OF DYNAMIC ASSEMBLIES
In general, the types of the System.Reflection.Emit namespace allow you to represent raw CIL
tokens programmatically during the construction of your dynamic assembly. You will see many of these
members in the example that follows; however, the ILGenerator type is worth checking out straightaway.
The Role of the System.Reflection.Emit.ILGenerator
As its name implies, the ILGenerator type’s role is to inject CIL opcodes into a given type member.
However, you cannot directly create ILGenerator objects, as this type has no public constructors; rather,
you receive an ILGenerator type by calling specific methods of the builder-centric types (such as the
MethodBuilder and ConstructorBuilder types). For example:
// Obtain an ILGenerator from a ConstructorBuilder
// object named "myCtorBuilder".
ConstructorBuilder myCtorBuilder =
new ConstructorBuilder(/* ...various args... */);
ILGenerator myCILGen = myCtorBuilder.GetILGenerator();
Once you have an ILGenerator in your hands, you are then able to emit the raw CIL opcodes using
any number of methods. Table 18-9 documents some (but not all) methods of ILGenerator.
Table 18-9. Various Methods of ILGenerator
Method
Meaning in Life
BeginCatchBlock()
Begins a catch block
BeginExceptionBlock()
Begins an exception block for a nonfiltered exception
BeginFinallyBlock()
Begins a finally block
BeginScope()
Begins a lexical scope
DeclareLocal()
Declares a local variable
DefineLabel()
Declares a new label
Emit()
Is overloaded numerous times to allow you to emit CIL opcodes
EmitCall()
Pushes a call or callvirt opcode into the CIL stream
EmitWriteLine()
Emits a call to Console.WriteLine() with different types of values
EndExceptionBlock()
Ends an exception block
EndScope()
Ends a le X