Compiling the Code

Compiling .NET code at runtime requires a number of steps. After you master this architecture, you can compile almost any code imaginable. Suppose you wish to compile the code shown in Listing 3-1.

Listing 3-1. Simple Code Sample string szCode = @"using System;

using System.Windows.Forms;

namespace RunTimeCompile {

public class MyClass {

public void DisplayMessage() {

MessageBox.Show(""Hello World"");

This code is a simple class that references a few assemblies and declares a class with one method that, when invoked, displays a message. To compile this code and display the message, you first need an instance of CodeDomProvider to which you pass the language of your choice:

oCodeDomProvider = CodeDomProvider.CreateProvider("CSharp");

Next, you need to tell the compiler a few things via the CompilerParameters object. Even though the code references the System and System.Windows .Forms namespaces via the using statement, you still need to make the compiler aware of these assemblies by adding them to the ReferencedAssemblies collection, as shown in Listing 3-2.

Listing 3-2. Referencing Assemblies

CompilerParameters oCompilerParameters = new CompilerParameters(); oCompilerParameters.ReferencedAssemblies.Add("system.dll"); oCompilerParameters.ReferencedAssemblies.Add("system.windows.forms.dll");

This is the programmatic equivalent of adding assemblies to the References node in the Solution Explorer. If you can't anticipate what assemblies the users will need, you can require them to enter using statements and then parse the code to retrieve the appropriate assembly names.

Next, the compiler needs to know how the output will be generated. Do you want an EXE or a DLL? In this case, you need a DLL, so the GenerateExecutable property should be set to false:

oCompilerParameters.GenerateExecutable = false;

■ Note If you want an EXE, you need to set up a Main() method in Listing 3-1 to serve as a point of entry. This is the only difference between and EXE and a DLL.

Likewise, this assembly shouldn't be written to disk, because it won't be used outside of the runtime of the host application. Therefore, set the GenerateInMemory property to true:

oCompilerParameters.GenerateInMemory = true;

Then, pass the CompilerParameters object to the CodeDomProvider's CompileAssemblyFromSource() method to produce a CompilerResults object like this:

oCompilerResults =

oCodeDomProvider.CompileAssemblyFromSource(oCompilerParameters, szCode);

Of course, you aren't restricted to compiling only a text-string representation of source code. You can use the CompileAssemblyFromFile() method to compile a series of files on disk, as shown in Listing 3-3.

Listing 3-3. Setting the Compiler Options

CompilerParameters oCompilerParameters = new CompilerParameters(); oCompilerParameters.GenerateInMemory = true; oCompilerParameters.GenerateExecutable = false; oCompilerParameters.IncludeDebugInformation = true; oCompilerParameters.ReferencedAssemblies.Add("system.dll"); oCompilerParameters.ReferencedAssemblies.Add("system.windows.forms.dll");

oCompilerResults = oCodeDomProvider.

CompileAssemblyFromFile(oCompilerParameters, aFiles);

You can also use the CompileAssemblyFromDom() method to compile a code graph created using the CodeCompileUnit class, described in Chapter 1.

0 0

Post a comment