Code Generation in multiple languages
I'm currently working on a personal project that needs to spit out code after parsing some XML file. I had previously used the .NET frameworks CodeDom to do on the fly compilation and hence tried digging it up to see if I could use it for code generation. In a small time I was completely blown over by the feature set and what I could achieve in a relatively small time.
I had initially expected to get little support from the framework and had thought I'd manipulate text to generate the C# code. I now figured out that I could use the CodeDom to build the code structure hierarchy and just pass on a language parameter and if that language is supported generate code using that language. Suddenly my application was not limited to C# but I could use VB.NET or VJ# for my output code as well. To demonstrate this I'd skip the XML parsing (serialization and logic) part. The following code generates a hello world program in any of the supported .NET language
private
void BtnGenerate_Click(object sender, EventArgs e)
{
TextCode.Text = GenerateCode("C#");
TextCode.Text += GenerateCode("VJ#");
TextCode.Text += GenerateCode("VB");
}
public string GenerateCode(string language)
{
// get CodeDom provider from the language name
CodeDomProvider provider =
CSharpCodeProvider.CreateProvider(language);
// generate the code
return GenerateCode(provider);
}
public string GenerateCode(CodeDomProvider provider)
{
// open string based in memory streams
using(StringWriter writer = new StringWriter())
using (IndentedTextWriter tw =
new IndentedTextWriter(writer, " "))
{
// create top level namespace
CodeNamespace myNamespace =
new CodeNamespace("AbhinabaNameSpace");
// create file level comment
CodeComment comment = new CodeComment(
string.Format("Generated on {0}",
DateTime.Now.ToLocalTime().ToShortDateString()),
false);
CodeCommentStatement commentStatement =
new CodeCommentStatement(comment);
myNamespace.Comments.Add(commentStatement);
// add using statements for the required namespaces
myNamespace.Imports.Add(
new CodeNamespaceImport("System"));
// define the one and only class
CodeTypeDeclaration mainClass =
new CodeTypeDeclaration();
mainClass.IsClass = true;
mainClass.Name = "HelloWorldMainClass";
mainClass.Attributes = MemberAttributes.Public;
myNamespace.Types.Add(mainClass);
//define the entry point which'd be
//Main method in C#
CodeEntryPointMethod mainMethod =
new CodeEntryPointMethod();
mainMethod.Comments.Add(
new CodeCommentStatement("<summary>", true));
mainMethod.Comments.Add(
new CodeCommentStatement("Entry point", true));
mainMethod.Comments.Add(
new CodeCommentStatement("</summary>", true));
mainClass.Members.Add(mainMethod);
//define the string variable message
CodeVariableDeclarationStatement strDecl =
new CodeVariableDeclarationStatement(
new CodeTypeReference(typeof(string)),
"message");
mainMethod.Statements.Add(strDecl);
//create the message = "hello world" statement
CodeAssignStatement ptxAssign =
new CodeAssignStatement(
new CodeVariableReferenceExpression("message"),
new CodeSnippetExpression("\"hello world\""));
mainMethod.Statements.Add(ptxAssign);
//call console.writeline to print the statement
CodeMethodInvokeExpression invokeConsoleWriteLine =
new CodeMethodInvokeExpression(
new CodeTypeReferenceExpression(typeof(Console)), "WriteLine",
new CodeExpression[]
{
new CodeArgumentReferenceExpression(
"message"),
}
);
mainMethod.Statements.Add(invokeConsoleWriteLine);
// code generation options
CodeGeneratorOptions opt = new CodeGeneratorOptions();
opt.BracingStyle = "C";
opt.BlankLinesBetweenMembers = false;
// generate the code and return it
provider.GenerateCodeFromNamespace(myNamespace, tw, opt);
return writer.ToString();
}
}
If only more languages were on .NET I could build the list in http://www2.latech.edu/~acm/HelloWorld.shtml in about couple of hours :)
I get the following output
In C#
=======
// Generated on 2/27/2006
namespace AbhinabaNameSpace
{
using System;
public class HelloWorldMainClass
{
///
/// Entry point
///
public static void Main()
{
string message;
message = "hello world";
System.Console.WriteLine(message);
}
}
}
VJ#
=======
// Generated on 2/27/2006
package AbhinabaNameSpace;
import System.*;
public class HelloWorldMainClass
{
/** Entry point */
public static void main(String[] args)
{
String message;
message = "hello world";
System.Console.WriteLine(message);
}
}
VB
=======
Imports System
'Generated on 2/27/2006
Namespace AbhinabaNameSpace
Public Class HelloWorldMainClass
'''
'''Entry point
'''
Public Shared Sub Main()
Dim message As String
message = "hello world"
System.Console.WriteLine(message)
End Sub
End Class
End Namespace