Fun with the CodeDOM

posted @ Wednesday, March 16, 2005 1:00 AM

 

I just realized tonight that it's been quite awhile since I've had a blog post. Things at work have kept me rather busy but they are finally starting to settle down now. I was talking to Tim Gifford earlier today about the use of CodeDOM. I decided to put together a little sample that shows you how to generate code on the fly. The example was just thrown together so there are obviously many modifications that can be done to clean this up, an exercise that will be left up to the reader. It's important to understand how the CodeDOM works if you ever build any tools that need to generate code. I have to admit that one of the strangest property values throughout the CodeDOM is the BracingStyle of the CodeGeneratorOptions class. The default string value is “Block”, which generates code with a Java style format where the beginning bracket doesn't get its own line, if you prefer a new line for your beginning brackets the value you use is “C”, why not just use an enumeration? Anyway, here is a sample function to generate C# code:

You need follow:
using System;
using
System.IO;
using
System.CodeDom;
using
Microsoft.CSharp;
using
System.Reflection;
using
System.CodeDom.Compiler;

// .....

public void Generate(string file)
{
Stream s
= File.Open(file, FileMode.Create);
StreamWriter writer = new StreamWriter(s);

// code generator
CSharpCodeProvider provider = new CSharpCodeProvider();
ICodeGenerator gen = provider.CreateGenerator(writer);
CodeGeneratorOptions genOpt = new CodeGeneratorOptions();
genOpt.BracingStyle = "C";
CodeSnippetCompileUnit compUnit =
new
CodeSnippetCompileUnit("using System;");
gen.GenerateCodeFromCompileUnit(compUnit, writer, genOpt);
writer.WriteLine();
// namespace decl.
CodeNamespace nmspace = new CodeNamespace("DeveloperNotes");
// public class
CodeTypeDeclaration cls = new CodeTypeDeclaration();
cls.Name = "Example";
cls.IsClass = true;
cls.TypeAttributes = TypeAttributes.Public;
writer.WriteLine();
// add class to namespace
nmspace.Types.Add(cls);

// private variable
CodeMemberField member =
new
CodeMemberField(typeof(string), "name = \"Nick\"");
member.Attributes = MemberAttributes.Private;
cls.Members.Add(member);
// public constructor
CodeConstructor constructor = new CodeConstructor();
constructor.Attributes = MemberAttributes.Public;
cls.Members.Add(constructor);
// public property
CodeMemberProperty prop = new CodeMemberProperty();
prop.Attributes = MemberAttributes.Public;
prop.Type = new CodeTypeReference(typeof(string));
prop.Name = "Name";
prop.HasGet = true;
CodeSnippetExpression cse =
new
CodeSnippetExpression("return name");
prop.GetStatements.Add(cse);
cls.Members.Add(prop);
// Main method
CodeMemberMethod main = new CodeMemberMethod();
main.Name = "Main";
main.ReturnType = new CodeTypeReference(typeof(void));
main.Attributes = MemberAttributes.Public
| MemberAttributes.Static
;
CodeSnippetStatement css0 = new CodeSnippetStatement();
css0.Value = "Example ex = new Example();";
CodeSnippetStatement css1 = new CodeSnippetStatement();
css1.Value = "Console.WriteLine(\"My name is: \" + ex.Name);";
CodeSnippetStatement css2 = new CodeSnippetStatement();
css2.Value = "Console.Read();";
main.Statements.Add(css0);
main.Statements.Add(css1);
main.Statements.Add(css2);
cls.Members.Add(main);
// output contents
gen.GenerateCodeFromNamespace(nmspace, writer, genOpt);
// clean up
writer.Close();
s.Close();
}

Generates the following code:

using System;
namespace
DeveloperNotes
{

public class Example
{

private string name = "Nick";

public
Example()
{
}

public virtual string Name
{
get
{
return name;
}
}

public static void Main()
{
Example ex
= new Example();
Console.WriteLine("My name is: " + ex.Name);
Console.Read();
}
}
}