BlackWaspTM
.NET Framework
.NET 3.5+

C# Runtime Compilation (2)

The .NET framework includes classes that allow the code generator and compiler to be controlled from within an assembly. This allows C# source code, held in a string array, to be compiled at run time and executed using basic reflection techniques.

Compiling the Code

The next step is to add the code that compiles some other code dynamically. To do so we use the CompileAssemblyFromSource method, passing the compiler options and the code to be compiled to its parameters. The code that will be compiled is provided as a string array. You can think of each element in the array as a string that contains the contents of a source file that would otherwise be created in Visual Studio. Each of the individual string elements must contain code that compiles correctly in order for the operation to succeed.

The result of the CompileAssemblyFromSource method is a CompilerResults object. If the code builds successfully, this holds the generated assembly in the CompiledAssembly property. If the build fails, the results can be interrogated to determine the problem. We will see this later in the article.

To compile the code, add the following line to the Main method. Note that the code to build is obtained from a method that we have yet to write:

CompilerResults results = provider.CompileAssemblyFromSource(parameters, GetCode());

To complete the first example we need to add the method that returns the string array of source code. This is shown below. Note that we are creating a string array with a single element. This element contains a using directive, a namespace, a class and a method. The method outputs the text, "Hello, world!" to the console. The text assigned to the string is formatted with indentation to show its structure but this is not necessary.

static string[] GetCode()
{
    return new string[]
    {
        @"using System;

        namespace DynamicNS
        {
            public static class DynamicCode
            {
                public static void DynamicMethod()
                {
                    Console.WriteLine(""Hello, world!"");
                }
            }
        }"
    };
}

Executing the Compiler Method

Once the assembly has been compiled and is held in memory, we can execute the method using reflection. To make access to the reflection classes simpler, add the following using directive:

using System.Reflection;

We won't look into reflection in detail as it is beyond the scope of this article. Simply add the following code to the end of the Main method, after the call to CompileAssemblyFromSource. The first line obtains a reference to the DynamicCode class. The second line gets the method and the third line executes it.

var cls = results.CompiledAssembly.GetType("DynamicNS.DynamicCode");
var method = cls.GetMethod("DynamicMethod", BindingFlags.Static | BindingFlags.Public);
method.Invoke(null, null);

You can now run the program. The output should be as follows:

Hello, world!
25 September 2011