RSS

Source code generation example using CodeDom

30 Jul

This example demonstrates how to generate source code automatically using .NET framework. It is also intended to serve as a quick reference of common tasks when coding against CodeDom. The example generates a Ford Focus class type in Automobile Namespace and the class inherits Car class. The generated class source code is at the bottom of this article.

// Create a compile unit
CodeCompileUnit compileUnit = new CodeCompileUnit();
// Define a Namespace
CodeNamespace automobileNamespace = new CodeNamespace("Automobile");
// Import Namespaces
automobileNamespace.Imports.Add(new CodeNamespaceImport("System"));

compileUnit.Namespaces.Add(automobileNamespace);

Importing namespaces in this manner puts the using directive in the Automobile namespace scope. Difference
of putting using inside or outside of the namespace is explained at
Should Usings be inside or outside the namespace.

// Define a class
CodeTypeDeclaration focusClass = new CodeTypeDeclaration("Focus");
// Inherit a type
focusClass.BaseTypes.Add("Car");

automobileNamespace.Types.Add(focusClass);

 

// Set custom attribute
CodeAttributeDeclaration codeAttribute = new CodeAttributeDeclaration("System.Serializable");
focusClass.CustomAttributes.Add(codeAttribute);
// Set class attribute
focusClass.IsClass = true;
focusClass.TypeAttributes = TypeAttributes.Public;

Making the class Serializable is only to demonstrate how to set custom attributes. For more info on serialization, visit Object Serialization using C#.

// Declare a class member field
CodeMemberField speedField = new CodeMemberField();
speedField.Attributes = MemberAttributes.Private;
speedField.Name = "_Speed";
speedField.Type = new CodeTypeReference(typeof(int));

focusClass.Members.Add(speedField);

 

// Define a property
CodeMemberProperty speedProperty = new CodeMemberProperty();
speedProperty.Attributes = MemberAttributes.Public | MemberAttributes.Final;
speedProperty.Name = "Speed";
speedProperty.HasGet = true;
speedProperty.Type = new CodeTypeReference(typeof(int));

speedProperty.GetStatements.Add(new CodeMethodReturnStatement(
    new CodeFieldReferenceExpression(new CodeThisReferenceExpression(), "_Speed")));

focusClass.Members.Add(speedProperty);

Setting MemberAttributes.Final removes the virtual attribute of the Speed property.

// Declare a method
CodeMemberMethod accelerateMethod = new CodeMemberMethod();
accelerateMethod.Attributes = MemberAttributes.Public;
accelerateMethod.Name = "Accelerate";

CodeFieldReferenceExpression speedFieldReference = new CodeFieldReferenceExpression(
    new CodeThisReferenceExpression(), "_Speed");

CodeBinaryOperatorExpression addExpression = new CodeBinaryOperatorExpression(
    speedFieldReference, CodeBinaryOperatorType.Add, new CodePrimitiveExpression(10));

CodeAssignStatement assignStatement = new CodeAssignStatement(speedFieldReference, addExpression);

accelerateMethod.Statements.Add(assignStatement);
focusClass.Members.Add(accelerateMethod);

 

// Declare the constructor
CodeConstructor constructor = new CodeConstructor();
constructor.Attributes = MemberAttributes.Public | MemberAttributes.Final;
// Add a parameter
constructor.Parameters.Add(new CodeParameterDeclarationExpression(typeof(int), "speed"));
// Add field initialization logic
constructor.Statements.Add(new CodeAssignStatement(
    speedFieldReference, new CodeArgumentReferenceExpression("speed")));

focusClass.Members.Add(constructor);

 

// Define the entry point
CodeEntryPointMethod entryPointMethod = new CodeEntryPointMethod();
CodeObjectCreateExpression focusObjectCreate = new CodeObjectCreateExpression(
    new CodeTypeReference("Focus"), new CodePrimitiveExpression(0));
// Add the statement: "Focus focus = new Focus(0);"
entryPointMethod.Statements.Add(new CodeVariableDeclarationStatement(
    new CodeTypeReference("Focus"), "focus", focusObjectCreate));
// Create the expression: "focus.Accelerate()"
CodeMethodInvokeExpression accelerateInvoke = new CodeMethodInvokeExpression(
    new CodeVariableReferenceExpression("focus"), "Accelerate");

entryPointMethod.Statements.Add(accelerateInvoke);
focusClass.Members.Add(entryPointMethod);
// Generate C# source code
CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
CodeGeneratorOptions options = new CodeGeneratorOptions();
options.BracingStyle = "C";
using (StreamWriter sourceWriter = new StreamWriter("C:\\Focus.cs"))
{
    provider.GenerateCodeFromCompileUnit(compileUnit, sourceWriter, options);
}

The generated code is listed below:

namespace Automobile
{
    using System;

    [System.Serializable()]
    public class Focus : Car
    {

        private int _Speed;

        public Focus(int speed)
        {
            this._Speed = speed;
        }

        public int Speed
        {
            get
            {
                return this._Speed;
            }
        }

        public virtual void Accelerate()
        {
            this._Speed = (this._Speed + 10);
        }

        public static void Main()
        {
            Focus focus = new Focus(0);
            focus.Accelerate();
        }
    }
}

References:
Using the CodeDOM
How to: Create a Class Using CodeDOM
CodeDOM Quick Reference

Advertisements
 
Leave a comment

Posted by on July 30, 2012 in .NET, C#, Code Generation

 

Tags: ,

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: