Sunday, November 16, 2008

Code Dom: A Step Ahead Series

Code Dom: A Step Ahead Series

Introduction:


This is a continuation to my earlier post C#-The Language : A Step Ahead Series-Part-II
The following code snippet showed the power of CODE DOM:

/* This Example is a part of different
* examples shown in Book:
* C#2005 Beginners: A Step Ahead
* Written by: Gaurav Arora
* Reach at : msdotnetheaven*/

// File name : CodeDomExpl.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.CodeDom;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using System.IO;

namespace CSharp.AStepAhead.CodeDomExpl
{
public class CodeDomExpl
{
public static void Main()
{
Console.Clear();
Console.Write("This will create a simple Console aplication\n");
Console.Write("\n Enter Namespace: ");
string nmSpace = Console.ReadLine();

Console.Write("\n Enter Class file name: ");
string fName = Console.ReadLine();

Console.Write("\n Enter Output file name: ");
string oFname = Console.ReadLine();

Console.Write("\n Enter Your message: ");
string msg = Console.ReadLine();

if (nmSpace.Length == 0)
nmSpace = "CSharp.AStepAhead.CodeDomExpl";
if (fName.Length==0)
fName = "CodeDomExpl.cs";
if (oFname.Length==0)
oFname ="CodeDomExpl.exe";
if (msg.Length==0)
msg = "Hello! I am created using CodeDom i.e. Code Document Object Model.";



//Validate enteries
nmSpace = CodeDomExpl.chkValid(nmSpace,0);
fName = CodeDomExpl.chkValid(fName,1);
oFname = CodeDomExpl.chkValid(oFname,2);
msg = CodeDomExpl.chkValid(msg,3);

//create an instance of the class
GenerateConsoleApp oC = new GenerateConsoleApp(nmSpace,fName,oFname,msg);
oC.CreateCode();
Console.WriteLine("\nApplication crated :\nSource File Name :{0}\nExecutable File Name :{1}", fName, oFname);
Console.ReadLine();
return;
}
public static string chkValid(string str,int id)
{
string newStr=string.Empty;
string filePath = @"F:\myWrittings\CSharpBook\Source Codes\CodeDomApplications\";
switch (id)
{
case 3: //message
{
newStr = str;

break;
}
case 2: //output file name
{

int i = str.IndexOf(".");

newStr = (i > 0) ? filePath + str.Substring(0, i) + ".exe" : filePath + str + ".exe";

break;
}



case 1: //class file name
{

int i = str.IndexOf(".");
newStr = (i > 0) ? filePath + str.Substring(0, i) + ".cs" : filePath + str + ".cs";

break;
}
case 0: //namespace
{

int i = str.IndexOf(".");
newStr = "CSharp.AStepAhead.";
newStr += (i > 0) ? str.Substring(0, i) : str;

break;
}
}
return newStr;

}
}

public class GenerateConsoleApp
{

public string nameSpace;
public string sourceFile;
public string executingFile;
public string customMessage;



public GenerateConsoleApp()
{
}
public GenerateConsoleApp(string nmSpace, string csFile,string exeFile,string msg)
{
nameSpace = nmSpace;
sourceFile = csFile;
executingFile = exeFile;
customMessage = msg;
}
public void CreateCode()
{
CodeCompileUnit unit = GenerateCode();

// Set up options for source code style
CodeGeneratorOptions opts = new CodeGeneratorOptions();
opts.BracingStyle = "C";
opts.IndentString = "\t";


// Create code generator and write code file
CSharpCodeProvider cscp = new CSharpCodeProvider();

ICodeGenerator gen = cscp.CreateGenerator();

StreamWriter sw = new StreamWriter(sourceFile);
gen.GenerateCodeFromCompileUnit(unit, sw, opts);
sw.Close();

CompilerParameters compilerParams = new CompilerParameters();
compilerParams.GenerateExecutable = true;

compilerParams.OutputAssembly = executingFile;

ICodeCompiler compiler = cscp.CreateCompiler();

compiler.CompileAssemblyFromFile(compilerParams, sourceFile);
}


private CodeCompileUnit GenerateCode()
{
CodeEntryPointMethod objMainMethod = new CodeEntryPointMethod();
objMainMethod.Name = "Main";

// generate this expression: Console
CodeTypeReferenceExpression consoleType = new CodeTypeReferenceExpression();
consoleType.Type = new CodeTypeReference(typeof(Console));

// Set up the argument list to pass to Console.WriteLine()
CodeExpression[] writeLineArgs = new CodeExpression[1];
CodePrimitiveExpression arg0 = new CodePrimitiveExpression(customMessage);
writeLineArgs[0] = arg0;

// generate this statement: Console.WriteLine(message)
CodeMethodReferenceExpression writeLineRef = new CodeMethodReferenceExpression(consoleType, "WriteLine");
CodeMethodInvokeExpression writeLine = new CodeMethodInvokeExpression(writeLineRef, writeLineArgs);

// generate this statement: Console.ReadLine()
CodeMethodReferenceExpression readLineRef = new CodeMethodReferenceExpression(consoleType, "ReadLine");
CodeMethodInvokeExpression readLine = new CodeMethodInvokeExpression(readLineRef);

// Add Main() method to a class
CodeTypeDeclaration theClass = new CodeTypeDeclaration();
theClass.Members.Add(objMainMethod);

string className = string.Empty;
//retrieve actual class name
int j = sourceFile.LastIndexOf(@"\");
int k = sourceFile.IndexOf(".");
className = sourceFile.Substring(j + 1, k - j - 1);


// Add both the code of WriteLine and Readline
objMainMethod.Statements.Add(writeLine);
objMainMethod.Statements.Add(readLine);

// Add namespace and add class
CodeNamespace ns = new CodeNamespace(nameSpace);
ns.Imports.Add(new CodeNamespaceImport("System"));
ns.Types.Add(theClass);

// Generate the Compile Unit
CodeCompileUnit unit = new CodeCompileUnit();
unit.Namespaces.Add(ns);

return unit;
}

}
}


To represent source code, CodeDOM elements are linked to each other to form a data structure known as a CodeDOM graph, which models the structure of some source code.

The System.CodeDom namespace defines types that can represent the logical structure of source code, independent of a specific programming language.

Simply, it is an object model which represents actually source code. It is designed to be language independent.

Some common uses for the CodeDOM include:



  • Templated code generation: generating code for ASP.NET, XML Web services client proxies, code wizards, designers, or other code-emitting mechanisms.

  • Dynamic compilation: supporting code compilation in single or multiple languages.

No comments:

Post a Comment