.Net, Azure and occasionally gamedev

Reflection (4/5) Dynamic code generation (Reflection.Emit)

2013/01/17

This is the fourth post in a series. All posts are short excerpts from my Reflection paper.

Dynamic code generation is the process of generating new code at runtime that would otherwise be tedious to write or may not even be known during development time.

A few quick examples to help get a better understanding:

Here's an example for a proxy class:

public class Author
{
    public string Name {get; set; }
}

public AuthorProxy : Author
{
    private bool _isDirty;
    public string Name
    {
        get
        {
            return base.Name;
        }
        set
        {
             if (Name == value)
                 return;
             _isDirty = true;
             base.Name = value;
        }
    }
}

An ORM would generate the AuthorProxy and return it to the application. Because it's derived from Author the application can still do everything with the author class but the proxy gets to store additional information.

Dynamic code generation via Reflection.Emit

Reflection.Emit is the most low level approach to generating dynamic code.

The programmer is essentially required to write each IL statement by hand.

IL is the platform independent code that every .Net language emits when it is being compiled.

.Net - at runtime - will then take the IL code and parse it through the JIT (Just in Time) Compiler that will generate the actual platform specific code (x86/x64/etc.).

Because the programmer emits direct IL code, he can also define a set of statements that is not possible in C# or other highlevel languages however he also has to write a lot more code now (think of Assembler vs. C++ with IL being the low-level Assembler code).

In this blogpost, I will not list any IL code itself, but will only describe the theoretical steps. For a sample and a more detailed explanation, see the last post of this series (includes samples + paper).

The process of emitting IL code is split into several steps:

For each type:

Finally, the AssemblyBuilder instance provides methods to Save/Load the finished dll.

If you decide to save it, a dll/exe will be created on disk with all your types and it will be identical to a dll created by Visual Studio. It would also be possible to load a dll at runtime without ever saving it to the disk.

The last step required is to generate the IL code that fills each method/property.

This can become quite complex, as a statement as simple as

sum += x;
counter++;

already requires 16 lines of IL code.

If you are interested in the IL code and how to write it, be sure to download the full paper + samples at the end of this blog series.

Next week, we will look at System.Linq.Expressions which makes it easier to write and express dynamic code.

tagged as C# and Reflection