Probably the biggest change in .NET 2.0 Framework is the
usage of CodeDomProvider extensively. This is an abstract class that comes
under the namespace System.CodeDom.Compiler. This class has various methods
that help us to compile a code and also generate the code. All the language
providers of .Net inherit this class. The CSharpCodeProvider class comes under
the Microsoft.CSharp namespace and inherits this class and implements all the
methods accordingly.
Let us now see how a code is executed with a complete code.
The Code snippet below explains how to compile a code at
runtime using CodeDOM. It explains all the basic classes and methods that help
to achieve the same. The code uses namespaces like “System.CodeDom,” “System.CodeDom.Compiler”
and “Microsoft.CSharp.” The code below assumes that the reader understands the
syntax of C# language and is well versed with the basic programming techniques.
Listing 1
CodeDomProvider codeDomProvider = new CSharpCodeProvider();
CompilerParameters compilerParameters = new CompilerParameters();
compilerParameters.GenerateExecutable = false;
string[]code =
{
@"namespace CodeDomTest1 { class Class1
{
//[STAThread]
static void Main(string[]args)
{
string str = "" Output "";
Console.WriteLine(str);
}
}
}
"};
CompilerResults compilerResults =
codeDomProvider.CompileAssemblyFromSource(compilerParameters, code);
CompilerErrorCollection compilerErrorCollection =
compilerResults.Errors;
CompilerParameters is a class from System.CodeDOM.Compiler
namespace that represents the parameters used to invoke a compiler. We can set
all the compiler parameters using this class. CompilerResults is a class that
encapsulates all the results of the output after compilation. CodeDomProvider
does that actual initiation of compiling the code by the method
CompileAssemblyFromSource. It takes two parameters, the code as an array of
strings and the compiler options by using the object of CompilerParameters. It
returns the results as a type CompilerResults.
Using CodeDOM technology for generating the Program
structure
All CodeDOM programs start out with the creation of
ICodeGenerator for the target language. The following code shows the creation
of the ICodeGenerator for C#.
The code snippet below explains how to create a program
structure at runtime using CodeDom. It explains all the basic classes and
methods that help to achieve the same. The code uses namespaces like
“System.CodeDom,” “System.CodeDom.Compiler” and “Microsoft.CSharp.” The code
below assumes that the reader understands the syntax of C# language and is well
versed with the basic programming techniques.
Listing 2
ICodeGenerator cg =new CSharpCodeProvider().CreateGenerator();
...
CSharpCodeProvider cdp = new CSharpCodeProvider();
cg = cdp.CreateGenerator();
The ICodeGenerator is used to generate the actual code once
a CodeDOM tree is built. To begin building our tree, we need to start with a
CodeNamespace object. This object will contain any types and import
directives. With the CodeNamespace object we can begin the tree. For the
following sample, several CodeNamespaceImport objects are used to generate
import directives for commonly used namespaces. The sample also needs to
generate a class construct and this is done by using a CodeTypeDeclaration and
setting the IsClass property to true. The following code demonstrates these
concepts.
Listing 3
CodeNamespace cnamespace = new CodeNamespace("Microsoft.Samples");
cnamespace.Imports.Add (new CodeNamespaceImport ("System") );
...
CodeTypeDeclaration co = new CodeTypeDeclaration (typeName +"List");
co.IsClass = true;
cnamespace.Types.Add (co);
At the end of the previous example, the class type
definition is added to the Types collection of the CodeNamespace object. This is
how a CodeDOM tree is built starting with a CodeNamespace object and working
down through classes to class members. Class members in turn contain different
types of code statements and expressions. Once the entire tree is built, the
entire source tree can be written with a call to GenerateCodeFromNamespace, a
method on ICodeGenerator. The methods being passed are the CodeNamespace
object and a TextWriter.
baseCompiler.GenerateCodeFromNamespace (cnamespace, w, null);