Programmatically Invoke the C# Compiler

Imagine you have just generated some code using a code generation technique, wouldn’t it be really cool to then programmatically call the C# language compiler and generate assemblies from the generated code?

Let’s imagine we used an Xslt transformation to generate some code:

    XslCompiledTransform transform = new XslCompiledTransform();
transform.Load("Program.xslt");
transform.Transform("Program.xml", "Program.cs");

 

Using the CSharpCodeProvider class we can now programmatically call the C# compiler to generate the executable assembly. We’ll begin by advising the compiler of some options we’d like it to use when compiling our code using the CompilerParameters class.

    CompilerParameters parameters = new CompilerParameters();

We’ll specify that the assembly to be created should be an executable and we’ll also specify such things as whether debug information should be included, the warning level, whether warnings should be treated as errors etc.

    parameters.GenerateExecutable = true;
parameters.IncludeDebugInformation = true;
parameters.GenerateInMemory = false;
parameters.TreatWarningsAsErrors = true;
parameters.WarningLevel = 3;
parameters.CompilerOptions = "/optimize";
parameters.OutputAssembly = "Program.exe";

 

Using the compiler parameters we can now compile the C# code using the CSharpCodeProvider class and get the results of the compilation as an instance of the CompilerResults class.

    CSharpCodeProvider codeProvider = new CSharpCodeProvider();
CompilerResults results = codeProvider.CompileAssemblyFromFile(parameters, new string[] { "Program.cs" });

 

While the code you generated is unlikely to have any compiler warnings or errors, other developers may be less fortunate and therefore they can access the Errors property of the CompilerResults class to determine what went wrong. Actually the Errors property contains both compiler errors and warnings although the following simple LINQ queries allow you to examine the warnings and errors in isolation.

    var warnings = from e in results.Errors.Cast<CompilerError>()
where e.IsWarning
select e;

    var errors = from e in results.Errors.Cast<CompilerError>()
where !e.IsWarning
select e;

While code generation is very cool, we generate code to ultimately create assemblies that we can either execute or reference from other code. If you’re programmatically generating code why not next time also programmatically generate the assemblies too!