An intro to CodeDom [David Gutierrez]

I recently gave a talk on CodeDom for compiler writers, and I thought I would adapt some of those slides here as a basic intro to CodeDom. 

CodeDom, or Code Document Object Model,  is a feature which lets you generate code and assemblies in a language neutral way.  It's also extensible, meaning it's possible to plug in a new provider and in theory get full support for that language.

CodeDom works with two parts.  First is the codedom tree, which is the language neutral part representing the code you want to generate.  The tree describes all parts of your code, from namespaces, types and methods down to individual statements.  There's some sample code farther down.  You'll see that building a tree for your code takes a lot of code, but it's relatively straightforward.  And for most people, creating CodeDom trees is the most interesting part about CodeDom.  They are simply in the business of generating code or assemblies and don't care about anything language specific. 

The second part is providers which are language specific and know how to turn a tree into code and compile it.  Compiler writers will be most interested in writing their own provider.  Generally, though, if you want to generate code you don't need to be too concerned about providers.

When should you use CodeDom?  If you're generating code on behalf of the user, you should use CodeDom so you aren't limited to a particular language.  This pertains to any code you might generate - as long as the user will see the code, there's a good chance they will want to control which language it's in.  Also if you're creating dynamic assemblies at runtime, you might want to use CodeDom as an alternative to Reflection.Emit or directly writing out code and starting a separate process to run the compiler.  Since the CodeDom model is closer to how one would write actual code, most people will find it easier than something as low level as Reflection.Emit.  CodeDom is also a lot more maintainable than doing everything manually.

And now here's "hello world" generated from codedom!:

 using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Reflection; public class Demo {
    public static void Main () {
        CodeCompileUnit ccu  = new CodeCompileUnit();         //namespace Foo {
        CodeNamespace namesp = new CodeNamespace("Foo");
        //    using System;
        namesp.Imports.Add(new CodeNamespaceImport("System"));
        ccu.Namespaces.Add(namesp);         //    public class Bar {
        CodeTypeDeclaration barType = new CodeTypeDeclaration("Bar");
        barType.TypeAttributes = TypeAttributes.Public;
        namesp.Types.Add(barType);         //        public void MyMethod() {
        CodeMemberMethod myMethod = new CodeMemberMethod();
        myMethod.Name = "MyMethod";
        myMethod.Attributes = MemberAttributes.Public;
        barType.Members.Add(myMethod);         //            Console.WriteLine("Hello World");
        CodeMethodReferenceExpression methodRef = new CodeMethodReferenceExpression();
        methodRef.MethodName = "WriteLine";
        methodRef.TargetObject = new CodeTypeReferenceExpression(typeof(Console));
        CodePrimitiveExpression methodArg = new CodePrimitiveExpression("Hello World");
        CodeMethodInvokeExpression methodInvoke = new CodeMethodInvokeExpression(methodRef, 
                                                           new CodeExpression[] {methodArg});
        myMethod.Statements.Add(new CodeExpressionStatement(methodInvoke));
         // Do some extra checks to help mitigate code-injection security holes. 
        CodeGenerator.ValidateIdentifiers(ccu);
            
        // change this line to generate code in C#, VB, jscript
        CodeDomProvider provider = CodeDomProvider.CreateProvider("VB");
        provider.GenerateCodeFromCompileUnit(ccu, Console.Out, new CodeGeneratorOptions());

    }
}

Also you might be interested to know about some of the parts of the Framework that use CodeDom today:

  • Asp.NET - generates code from its aspx pages
  • Wsdl.exe - creates code for web service client
  • Xsd.exe - generates class to read xml according to an XSD schema
  • Resgen.exe - can create strongly typed resources to make it easy to read your resources