Generating Source Code and Compiling a Program 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.
Using a CodeDOM code provider to generate source code
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:
Dim provider As New 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 Shared Function GenerateCSharpCode( _
compileunit As CodeCompileUnit) As String
' Generate the code with the C# code provider.
Dim provider As CSharpCodeProvider = New CSharpCodeProvider()
' Build the output file name.
Dim sourceFile As String
If provider.FileExtension.StartsWith(".")
sourceFile = "HelloWorld" + provider.FileExtension
Else
sourceFile = "HelloWorld." + provider.FileExtension
End If
' Create a TextWriter to a StreamWriter to an output file.
Dim tw As New IndentedTextWriter( _
New StreamWriter(sourceFile, False), " ")
' Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit(compileunit, tw, _
New CodeGeneratorOptions())
' Close the output file.
tw.Close()
Return sourceFile
End Function
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.
IndentedTextWriter tw = new IndentedTextWriter(
new StreamWriter(sourceFile, false), " ");
// Generate source code using the code provider.
provider.GenerateCodeFromCompileUnit(compileunit, tw,
new CodeGeneratorOptions());
// Close the output file.
tw.Close();
return sourceFile;
}
Using a CodeDOM code provider to compile assemblies
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 Shared Function CompileCSharpCode(sourceFile As String, _
exeFile As String) As Boolean
Dim provider As CSharpCodeProvider = New CSharpCodeProvider()
' Build the parameters for source compilation.
Dim cp As New CompilerParameters()
' Add an assembly reference.
cp.ReferencedAssemblies.Add("System.dll")
' Save the assembly as a physical file.
cp.GenerateInMemory = False
' Generate an executable instead of a class library.
cp.GenerateExecutable = True
' Set the assembly file name to generate.
cp.OutputAssembly = exeFile
' Invoke compilation.
Dim cr As CompilerResults = _
provider.CompileAssemblyFromFile(cp, sourceFile)
If cr.Errors.Count > 0 Then
' Display compilation errors.
Console.WriteLine("Errors building {0} into {1}", _
sourceFile, cr.PathToAssembly)
Dim ce As System.CodeDom.Compiler.CompilerError
For Each ce In cr.Errors
Console.WriteLine(" {0}", ce.ToString())
Console.WriteLine()
Next ce
Else
Console.WriteLine("Source {0} built into {1} successfully.", _
sourceFile, cr.PathToAssembly)
End If
' Return the results of compilation.
If cr.Errors.Count > 0 Then
Return False
Else
Return True
End If
End Function
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;
}
}
Languages with Initial Support
The .NET Framework provides code compilers and code generators for the following languages: C#, Visual Basic, C++, J#, and JScript. CodeDOM support can be extended to other languages by implementing language-specific code generators and code compilers.
See Also
Reference
CodeDOM Quick Reference
System.CodeDom
System.CodeDom.Compiler