Introducing Code Generation - Creating the Template
(Page 3 of 13 )
The procedure that creates the sample “Hello World” program has a single shared method named GenerateOutput. It creates a StreamWriter that implicitly creates a stream. WriteLine outputs each line of the target code. The Finally block flushes and closes the stream:
' Class Summary: Create Hello World program using direct stream output
Public Class HelloWorldViaBruteForce
#Region "Public Methods and Properties"
Public Shared Sub GenerateOutput(ByVal outputFileName _
As String)
Dim writer As IO.StreamWriter
Try
writer = New IO.StreamWriter(outputFileName)
writer.WriteLine("Option Strict On")
writer.WriteLine("Option Explicit On")
writer.WriteLine("")
writer.WriteLine("Imports System")
writer.WriteLine("")
writer.WriteLine("' Class Summary: Hello World _
target output")
writer.WriteLine("") writer.WriteLine("Public Class_
TargetOutput")
writer.WriteLine("") writer.WriteLine("#Region " & _
Chr(34) & _ "Public Methods and Properties" & Chr(34))
writer.WriteLine(" Public Shared Sub Main()")
writer.WriteLine(" Console.WriteLine(" & Chr(34) & _
"Hello World" & Chr(34) & ")")
writer.WriteLine(" End Sub")
writer.WriteLine("#End Region")
writer.WriteLine("")
writer.WriteLine("End Class")
Finally
If Not writer Is Nothing Then
writer.Flush()
writer.Close()
End If
End Try
End Sub
#End Region
End Class
This code resembles what many people who’ve played a bit with code generation have done. It uses a standard StreamWriter and explicitly handles horizontal whitespace via hard-coded spaces.
**************
NOTE Outputting an empty string (“”) using WriteLine creates a blank line in your output.
I find the layering of .NET code on .NET code in this sample to be rather mind bending. Option Strict appears twice, at the top of the code and again as a quoted string to be output. I find it difficult to read the code and mentally separate the instructions that are currently running from those that are part of the template. Imagine extending this to hundreds or thousands of lines of code-generating source!
Other than this problem and some ugliness in the quotes, this code is straightforward. This code works very well and reliably, and you don’t have to learn anything new to use it. These are important benefits, but the long-term maintainability of code with long output blocks is poor—unless you’re vigilant about your template organization. Otherwise, it’s difficult to trace problems in the output back to the generating code. In Chapter 3, I’ll show you how organizational tricks such as regions along with separate methods to generate each region make it easier to trace between your templates and output code.
Running the Template
Because the sample manages its own streams, generating the code for this simple brute-force sample just requires calling the shared method of the template class:
' Generate Hello World using Brute Force
HelloWorldViaBruteForce.GenerateOutput(IO.Path.Combine_
(outputDir, "HelloWorldViaBruteForce.vb"))
***************
NOTE Chapter 3 shows a more sophisticated way to run brute-force templates that makes it easy to output multiple files, such as running a particular template for every table in your metadata.
Generating “Hello World” via CodeDOM Remarkable changes have occurred at Microsoft during the past five years. Evidence of Microsoft’s increasing openness is the development of internal tools as first-class features, such as the CodeDOM. Visual Studio .NET uses the CodeDOM to create the strongly typed DataSet and in several places to create User Interface (UI) supporting code. The CodeDOM allows you to create an abstract model of your code as a containment hierarchy of objects that represent every namespace, class, method, statement, expression, comparison, variable occurrence, and so on. This abstraction isn’t simple. It results in a tree diagram, or CodeDOM graph, of the code. Unless you’re a compiler jock, this graph is probably quite different from the sequential manner you generally use to think about the code in your applications.
There’s one payback for this effort. Once you create an abstraction of your target code, the code generator can create the code in any supported language.
You can even output code in new languages as soon as someone creates a CodeDOM provider. Unfortunately, this benefit comes at a high price because code generation using the CodeDOM is quite complex, and many language features aren’t supported. Chapter 3 goes into these issues in more detail.
This chapter is from Code Generation in Microsoft .NET by Kathleen Dollard (Apress, 2004, ISBN: 1590591372). Check it out at your favorite bookstore today.
Buy this book now. |
Next: Running the Template >>
More .NET Articles
More By Apress Publishing