Export (0) Print
Expand All
1 out of 3 rated this helpful - Rate this topic

Generating and Compiling Source Code from a CodeDOM Graph

The System.CodeDom.Compiler namespace provides interfaces for generating source code from CodeDOM object graphs and for managing compilation with supported compilers. A code provider can produce source code in a particular programming language according to a CodeDOM graph. A class that derives from CodeDomProvider can typically provide methods for generating and compiling code for the language the provider supports.

To generate source code in a particular language, you need a CodeDOM graph that represents the structure of the source code to generate.

The following example demonstrate how to create an instance of a CSharpCodeProvider:

CSharpCodeProvider provider = new CSharpCodeProvider();

The graph for code generation is typically contained in a CodeCompileUnit. To generate code for a CodeCompileUnit that contains a CodeDOM graph, call the GenerateCodeFromCompileUnit method of the code provider. This method has a parameter for a TextWriter that it uses to generate the source code, so it is sometimes necessary to first create a TextWriter that can be written to. The following example demonstrates generating code from a CodeCompileUnit and writing the generated source code to a file named HelloWorld.cs.

public static string GenerateCSharpCode(CodeCompileUnit compileunit)
{
    // Generate the code with the C# code provider.
    CSharpCodeProvider provider = new CSharpCodeProvider();

    // Build the output file name. 
    string sourceFile;
    if (provider.FileExtension[0] == '.')
    {
       sourceFile = "HelloWorld" + provider.FileExtension;
    }
    else
    {
       sourceFile = "HelloWorld." + provider.FileExtension;
    }

    // Create a TextWriter to a StreamWriter to the output file. 
    using (StreamWriter sw = new StreamWriter(sourceFile, false))
    {
        IndentedTextWriter tw = new IndentedTextWriter(sw, "    ");

        // Generate source code using the code provider.
        provider.GenerateCodeFromCompileUnit(compileunit, tw,
            new CodeGeneratorOptions());

        // Close the output file.
        tw.Close();
    }

    return sourceFile;
}

Invoking compilation

To compile an assembly using a CodeDom provider, you must have either source code to compile in a language for which you have a compiler, or a CodeDOM graph that source code to compile can be generated from.

If you are compiling from a CodeDOM graph, pass the CodeCompileUnit containing the graph to the CompileAssemblyFromDom method of the code provider. If you have a source code file in a language that the compiler understands, pass the name of the file containing the source code to the CompileAssemblyFromFile method of the CodeDom provider. You can also pass a string containing source code in a language that the compiler understands to the CompileAssemblyFromSource method of the CodeDom provider.

Configuring compilation parameters

All of the standard compilation-invoking methods of a CodeDom provider have a parameter of type CompilerParameters that indicates the options to use for compilation.

You can specify a file name for the output assembly in the OutputAssembly property of the CompilerParameters. Otherwise, a default output file name will be used.

By default, a new CompilerParameters is initialized with its GenerateExecutable property set to false. If you are compiling an executable program, you must set the GenerateExecutable property to true. When the GenerateExecutable is set to false, the compiler will generate a class library.

If you are compiling an executable from a CodeDOM graph, a CodeEntryPointMethod must be defined in the graph. If there are multiple code entry points, it may be necessary to set the MainClass property of the CompilerParameters to the name of the class that defines the entry point to use.

To include debug information in a generated executable, set the IncludeDebugInformation property to true.

If your project references any assemblies, you must specify the assembly names as items in a StringCollection as the ReferencedAssemblies property of the CompilerParameters you use when invoking compilation.

You can compile an assembly that is written to memory rather than disk by setting the GenerateInMemory property to true. When an assembly is generated in memory, your code can obtain a reference to the generated assembly from the CompiledAssembly property of a CompilerResults. If an assembly is written to disk, you can obtain the path to the generated assembly from the PathToAssembly property of a CompilerResults.

To specify a custom command-line arguments string to use when invoking the compilation process, set the string in the CompilerOptions property.

If a Win32 security token is required to invoke the compiler process, specify the token in the UserToken property.

To link a Win32 resource file into the compiled assembly, specify the name of the Win32 resource file in the Win32Resource property.

To specify a warning level at which to halt compilation, set the WarningLevel property to an integer that represents the warning level at which to halt compilation. You can also configure the compiler to halt compilation if warnings are encountered by setting the TreatWarningsAsErrors property to true.

The following code example demonstrates compiling a source file using a CodeDom provider derived from the CodeDomProvider class.

public static bool CompileCSharpCode(string sourceFile, string exeFile)
{
    CSharpCodeProvider provider = new CSharpCodeProvider();

    // Build the parameters for source compilation.
    CompilerParameters cp = new CompilerParameters();

    // Add an assembly reference.
    cp.ReferencedAssemblies.Add( "System.dll" );

    // Generate an executable instead of 
    // a class library.
    cp.GenerateExecutable = true;

    // Set the assembly file name to generate.
    cp.OutputAssembly = exeFile;

    // Save the assembly as a physical file.
    cp.GenerateInMemory = false;

    // Invoke compilation.
    CompilerResults cr = provider.CompileAssemblyFromFile(cp, sourceFile);

   if (cr.Errors.Count > 0)
   {
       // Display compilation errors.
        Console.WriteLine("Errors building {0} into {1}",
            sourceFile, cr.PathToAssembly);
        foreach (CompilerError ce in cr.Errors)
        {
            Console.WriteLine("  {0}", ce.ToString());
            Console.WriteLine();
        }
    }
    else
    {
        Console.WriteLine("Source {0} built into {1} successfully.",
            sourceFile, cr.PathToAssembly);
    }

    // Return the results of compilation. 
    if (cr.Errors.Count > 0)
    {
        return false;
    }
    else
    {
        return true;
    }
}

The .NET Framework provides code compilers and code generators for the following languages: C#, Visual Basic, C++, and JScript. CodeDOM support can be extended to other languages by implementing language-specific code generators and code compilers.

Did you find this helpful?
(1500 characters remaining)
Thank you for your feedback
Show:
© 2014 Microsoft. All rights reserved.