Using the CodeDOM
Pages: 1, 2, 3
Displaying the Generated Code
For demonstration purposes, we will use a simple .aspx file with four labels, one for each of the languages being produced.
<table width="800" border="1">
<tr>
<th>VB.NET Code</th>
</tr>
<tr >
<td>
<asp:Label ID="vbCode" Runat="server" CssClass="code">
</asp:Label>
</td>
</tr>
<tr>
<th>
C# Code</th></tr>
<tr>
<td><asp:Label ID="csharpcode" Runat="server" CssClass="code">
</asp:Label></td>
</tr>
<tr>
<th>J# Code</th></tr>
<tr >
<td>
<asp:Label ID="JSharpCode" Runat="server" CssClass="code">
</asp:Label>
</td>
</tr>
<tr>
<th>JScript.NET</th>
</tr>
<tr>
<td><asp:Label ID="JScriptCode" Runat="server" CssClass="code">
</asp:Label></td>
</tr>
</table>
In the code behind, we will instantiate an instance of the CodeDomProvider
class that we created earlier and then set the value of the code properties to
the Text properties of the corresponding labels on the .aspx page. To make the
generated code look a little nicer on the web page, we will do some very simple
formatting to replace new lines with an HTML line break, and little spaces with
the HTML entity for a non breaking space.
private string FormatCode (string CodeToFormat)
{
string FormattedCode = Regex.Replace (CodeToFormat, "\n", "<br>");
FormattedCode = Regex.Replace (FormattedCode, " " , " ");
FormattedCode = Regex.Replace (FormattedCode, ",", ", ");
return FormattedCode;
}
Now we simply assign the generated code to the corresponding Labels in the
.asp page.
private void Page_Load(object sender, System.EventArgs e)
{
HelloWorld.CodeDomProvider codegen = new HelloWorld.CodeDomProvider ();
vbCode.Text = FormatCode (codegen.VBCode);
csharpcode.Text = FormatCode (codegen.CSharpCode);
JScriptCode.Text = FormatCode (codegen.JScriptCode);
JSharpCode.Text = FormatCode (codegen.JSharpCode);
Page.EnableViewState = false;
}
The output should look similiar to this:
VB.NET Code
Imports System
Imports System.Text
Namespace HelloWorld
Public Class Hello_World
Public Shared Sub Main()
Dim sbMessage As System.Text.StringBuilder = _
New System.Text.StringBuilder
Dim Characters() As Char = New Char() {_
Microsoft.VisualBasic.ChrW(72), _
Microsoft.VisualBasic.ChrW(69), _
Microsoft.VisualBasic.ChrW(76), _
Microsoft.VisualBasic.ChrW(76), _
Microsoft.VisualBasic.ChrW(79), _
Microsoft.VisualBasic.ChrW(32), _
Microsoft.VisualBasic.ChrW(87), _
Microsoft.VisualBasic.ChrW(79), _
Microsoft.VisualBasic.ChrW(82), _
Microsoft.VisualBasic.ChrW(76), _
Microsoft.VisualBasic.ChrW(68)}
Dim intCharacterIndex As Integer = 0
Do While intCharacterIndex < Characters.Length
sbMessage.Append(Characters(intCharacterIndex))
intCharacterIndex = intCharacterIndex + 1
Loop
Console.WriteLine (sbMessage.ToString())
End Sub
End Class
End Namespace
C# Code
namespace HelloWorld
{
using System;
using System.Text;
public class Hello_World
{
public static void Main()
{
System.Text.StringBuilder sbMessage = new
System.Text.StringBuilder();
char[] Characters = new char[] {
'H',
'E',
'L',
'L',
'O',
' ',
'W',
'O',
'R',
'L',
'D'};
for (int intCharacterIndex = 0;
intCharacterIndex < Characters.Length;
intCharacterIndex = intCharacterIndex + 1)
{
sbMessage.Append(Characters[intCharacterIndex]);
}
Console.WriteLine (sbMessage.ToString());
}
}
}
J# Code
package HelloWorld;
import System.*;
import System.Text.*;
public class Hello_World
{
public static void main(String[] args)
{
System.Text.StringBuilder sbMessage = new
System.Text.StringBuilder();
char[] Characters = new char[]
{
'H',
'E',
'L',
'L',
'O',
' ',
'W',
'O',
'R',
'L',
'D'}
;
for (int intCharacterIndex = 0;
intCharacterIndex < Characters.Length;
intCharacterIndex = intCharacterIndex + 1)
{
sbMessage.Append(Characters[intCharacterIndex]);
}
Console.WriteLine (sbMessage.ToString());
}
}
JScript.NET Code
//@cc_on
//@set @debug(off)
import System;
import System.Text;
package HelloWorld
{
public class Hello_World
{
public static function Main()
{
var sbMessage : System.Text.StringBuilder =
new System.Text.StringBuilder();
var Characters : char[] =
['H', 'E', 'L', 'L', 'O', ' ', 'W', 'O', 'R', 'L', 'D'];
for (var intCharacterIndex : int = 0;
; intCharacterIndex < Characters.Length;
intCharacterIndex = intCharacterIndex + 1)
{
sbMessage.Append(Characters[intCharacterIndex]);
}
Console.WriteLine (sbMessage.ToString());
}
}
}
HelloWorld.Hello_World.Main();
Conclusion
The CodeDom drives home the point that in .NET, the language is not nearly as important as the framework. This article demonstrated how to use some of the more common objects on the CodeDom that will probably be used in nearly every application of the CodeDom. The possibilities for structured code generation is really limited only by your imagination. I look forward to hearing some of the ways you are using the CodeDom.
Nick Harrison UNIX-programmer-turned-.NET-advocate currently working in Charlotte, North Carolina using .NET to solve interesting problems in the mortgage industry.
Return to ONDotnet.com
Showing messages 1 through 8 of 8.
-
Correctness of Programs generated in CodeDOM
2003-09-04 01:25:52 anonymous2 [Reply | View]
Hi Nick,
I have a question regarding the program graphs that we generate using CodeDOM. As I see it, it is quite possible to create a semantically incorrect program and still get CodeDOM to generate code for it. For example, I could Create a CodeAssignmentStatement with non-compatible left and right expressions. Or, worse still, create a CodeIterationStatement and not give its InitExpression at all! Or, a program graph that may be acceptable by one language may not be acceptable by another. Have you come across any article that has such information about incorrect Code Generation?
-
Clarification required regarding code in article
2003-03-12 05:39:35 mangeshminal [Reply | View]
Hi Nick,
Thank you very much for an interesting article.
While going thro' the article, I stumbled across 1 point - function for 'Initializing an Array'
In this function, CodePrimitiveExpression cpe is assigned as
cpe = CodePrimitiveExpression[Characters.Length];
Following this statement, there is a for loop which is used to create objects, for array of CodePrimitiveExpressions. This for loop is written as follows :
for (int i = 0; i < Name.Length ; i++)
{
cpe[i] = new CodePrimitiveExpression (Characters[i]);
}
My question is : What is the significance of Name.Length in for loop.
As per my understanding, for loop required to be as follows :
for (int i = 0; i < Characters.Length ; i++)
{
cpe[i] = new CodePrimitiveExpression (Characters[i]);
}
Will you please clarify my doubt ?
Waiting for your response...
Regards,
--- Shivprasad Mangesh Bhide -
Clarification required regarding code in article
2003-03-12 06:20:04 neh123us@yahoo.com [Reply | View]
Sorry for the confusion. You are correct. The for loop should be structured like:
for (int i = 0; i < Characters.Length ; i++)
{
cse[i] = new CodePrimitiveExpression (Characters[i]);
}
Let me know if you have any additional questions, or see any other problems.
Nick
-
Doesn't work!
2003-02-11 11:26:35 Steve Peters [Reply | View]
This article seemed very interesting. Unfortunately, I had to spend a lot of time getting the code to work. In fact, there are SEVERAL syntax errors within the code. Rather than having a disjointed example with chunks of code all over the place, it would have been much better to get the code all in one place, such as a complete listing at the end, or a link to download it. -
Doesn't work!
2003-02-12 18:52:22 neh123us@yahoo.com [Reply | View]
I am sorry that you had difficulty getting the sample code to work. In the future I will try to make it easier to get the complete source code. -
Doesn't work!
2004-02-12 15:58:37 dipin [Reply | View]
Is it possible for you to make the complete source code available? -
Doesn't work!
2004-12-10 07:16:29 PaulHayman [Reply | View]
Changes Required..
1) Change the following Line in CodeVariableDeclarationStatement method :
CodePrimitiveExpression[] cpe = new CodePrimitiveExpression[Characters.Length];
to
CodePrimitiveExpression[] cpe = new CodePrimitiveExpression[Characters.Length-1];
2) Use these namespaces in your class:
using System;
using System.IO;
using System.CodeDom;
using System.Text;
using System.CodeDom.Compiler;
using Microsoft.CSharp;
using Microsoft.VisualBasic;
3) Move the CurrentNamespace variable outside the CodeComProvider so it is in scope for the GenerateCode method.
4) In the CSharpCode property, change the return statement so that it returns GenerateCode() rather than GeneratorCode()
I could post my working solution to an email address if you wish.
Paul





