Browse DevX
Sign up for e-mail newsletters from DevX


Generate .NET Code in Any Language Using CodeDOM  : Page 4

The CodeDOM namespace contains classes that abstract the idea of code. After defining code in this abstract manner, you can use a language-specific CodeProvider class to generate code in any .NET language from that single abstract CodeDOM representation.




Building the Right Environment to Support AI, Machine Learning and Deep Learning

Simplify the Process
The preceding code shows the linear inline process to create the CodeDOM representation of a class; however, you can simplify the process considerably by wrapping up the code to create various types, members, and statements in easier-to-use methods. For example, here are three wrapper methods that simplify adding member fields to a class, creating a class constructor, and assigning a value to a member field.

Wrapper method to create a member field

' create a member field Private Function CreateField( _ ByVal fieldType As Type, _ ByVal fieldname As String, _ ByVal scope As MemberAttributes) Dim cmf As New CodeMemberField(fieldType, _ fieldname) cmf.Attributes = scope Return cmf End Function

Wrapper method to create a constructor

' create a constructor Private Function CreateConstructor(_ ByVal aClass As CodeTypeDeclaration, _ ByVal scope As MemberAttributes, _ ByVal params As CodeParameterDeclarationExpressionCollection, _ ByVal Statements As CodeStatementCollection) _ As CodeConstructor ' create a class constructor with the ' appropriate scope attribute Dim aClassConstructor As New CodeConstructor() aClassConstructor.Attributes = scope ' assign parameters If Not params Is Nothing Then aClassConstructor.Parameters.AddRange(params) End If ' add statements If Not Statements Is Nothing Then aClassConstructor.Statements.AddRange _ (Statements) End If Return aClassConstructor End Function

Wrapper method to assign a vaue to a member field

' assign a value to a member field Private Function CreateFieldAssignment( _ ByVal aClass As CodeTypeDeclaration, _ ByVal assignTo As String, _ ByVal assignFrom As String) Return New CodeAssignStatement( _ New CodeFieldReferenceExpression( _ New CodeThisReferenceExpression(), _ assignTo), New CodeArgumentReferenceExpression _ (assignFrom)) End Function

Even with only these few wrapper methods, you can see that the process to create a new namespace containing a class with a private member field, a constructor with one parameter, and a field assignment is considerably simpler than writing the CodeDOM code directly. Here's an example that uses the wrapper methods rather than the in-line method shown in the first part of this article.

Private Sub btnAutomate_Click(_ ByVal sender As System.Object, _ ByVal e As System.EventArgs) _ Handles btnAutomate.Click Dim VbProvider As New VBCodeProvider() Dim aClass As New CodeTypeDeclaration() ' create a public class aClass.Name = "AutoGen" ' add a private field aClass.Members.Add(CreateField( _ GetType(String), "myPrivateVariable", _ MemberAttributes.Private)) ' create a parameters collection Dim params As New _ CodeParameterDeclarationExpressionCollection() ' add a string parameter params.Add(New _ CodeParameterDeclarationExpression( _ GetType(String), "someValue")) ' create a statements collection Dim statements As New CodeStatementCollection() ' add a field assignment statement statements.Add(CreateFieldAssignment(aClass, _ "myPrivateVariable", "someValue")) ' create the class constructor aClass.Members.Add( _ CreateConstructor( _ aClass, MemberAttributes.Public, _ params, statements)) ' generate the code in VB.NET Dim sb As New StringBuilder() Dim sw As StringWriter = New StringWriter(sb) Dim codeGen As ICodeGenerator = VbProvider.CreateGenerator() codeGen.GenerateCodeFromType(aClass, sw, Nothing) ' show the results Me.txtResult.Text = "VB.NET CODE " & _ vbCrLf & vbCrLf Me.txtResult.AppendText(sb.ToString() & _ vbCrLf & vbCrLf) ' generate the code in C# sb = New StringBuilder() sw = New StringWriter(sb) Dim CSProvider As New _ Microsoft.CSharp.CSharpCodeProvider() codeGen = CSProvider.CreateGenerator() codeGen.GenerateCodeFromType(aClass, sw, Nothing) Me.txtResult.AppendText("C# CODE " & _ vbCrLf & vbCrLf) Me.txtResult.AppendText(sb.ToString()) End Sub

This time, the code creates a public class named AutoGen with a private String member field named myPrivateVariable. The AutoGen class creates a constructor that accepts a String parameter, and assigns the parameter value to the private member field. When a user clicks the "Automate CodeDOM" button on the sample form to run the preceding method, you'll see this code in the txtResult TextBox (see Figure 2):

Figure 2: When you click the "Automate CodeDOM" button, the sample form generates the code for the AutoGen class and displays it in the TextBox.

VB.NET CODE Public Class AutoGen Private myPrivateVariable As String Public Sub New(ByVal someValue As String) MyBase.New Me.myPrivateVariable = someValue End Sub End Class C# CODE public class AutoGen { private string myPrivateVariable; public AutoGen(string someValue) { this.myPrivateVariable = someValue; } }

Note that this example uses a different GenerateCodeFrom... method. This example contains only a class, not a complete namespace; therefore, the code calls the generator's GenerateCodeFromType method, rather than the GenerateCodeFromNamespace method used in the first example.

What's the Point?
You can use these techniques to write wizards to reduce repetitive coding tasks, to generate GUI code, or to emit code customized by users. For example, Microsoft uses the CodeDOM in Visual Studio to create abstract representations of typed DataSet classes that use the field names and types from a table or query specified by a developer. They then emit the code for the typed DataSet in the same language that the user selected for the project.

Finally, CodeDOM functionality isn't limited to generating source code; it also contains methods to compile code, so you can compile your generated code to an assembly at runtime. The combination provides a powerful way to create, compile, and execute customized code created at runtime as well as design time.

A. Russell Jones is DevX's Executive Editor. He's a former reptile keeper and professional musician who now composes computer applications. His most recent books are Mastering ASP.NET with VB.NET and Mastering ASP.NET with Visual C# (both published by Sybex). Reach him by e-mail at rjones@devx.com.
Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date