.NET
  Home arrow .NET arrow Page 4 - Introducing Code Generation
ASP Free Forums 
.NET  
ASP  
ASP Code  
ASP.NET  
ASP.NET Code  
BrainDump  
C#  
Code Examples  
Database  
Database Code  
IIS  
Microsoft Access  
MS SQL Server  
Visual Basic.NET  
Windows Scripting  
Windows Security  
XML  
ASP Web Hosting  
ASP.NET Web Hosting 
Dedicated Servers 
Moblin 
JMSL Numerical Library 
Windows Web Hosting
 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
.NET

Introducing Code Generation
By: Apress Publishing
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 4 stars4 stars4 stars4 stars4 stars / 9
    2004-12-08

    Table of Contents:
  • Introducing Code Generation
  • Generating a Simple Program
  • Creating the Template
  • Running the Template
  • Plain-Vanilla Code
  • Picking the Right Mechanism
  • Breaking Down the Code Generation Process
  • Writing Handcrafted Code
  • Tying It Together: Implementation and Testing
  • The Strongly Typed Dataset
  • Performing Real-World Code Generation
  • Generating a Simple Class via CodeDOM
  • Generating a Simple Class via XSLT Templates

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Introducing Code Generation - Running the Template


    (Page 4 of 13 )

    Before looking at how you create a CodeDOM graph, you’ll learn how you use it to output code. There are two steps to generation—creating a CodeDOM graph and generating the code. The first step creates a CodeCompileUnit as a container for the CodeDOM graph as well as some other information using BuildGraph. A separate step passes this CodeCompileUnit to the GenerateViaCodeDOM method that generates the code. This method takes the CodeCompileUnit and a CodeDomProvider as parameters. The CodeDomProvider is language specific and indicates how to translate the CodeDOM graph into actual code. Microsoft supplies CodeDOM providers for C#, VB .NET, and J#. To illustrate the flexibility of the CodeDOM, I use a single CodeCompileUnit with both a C# and a VB .NET provider. The result is code output in two languages:

    Dim compileUnit As CodeDom.CodeCompileUnit
    Dim provider As CodeDom.Compiler.CodeDomProvider
    compileUnit = HelloWorldViaCodeDOM.BuildGraph()
    provider = New Microsoft.VisualBasic.VBCodeProvider
    GenerateViaCodeDOM(IO.Path.Combine(outputDir, _
                           "HelloWorldViaCodeDOM.vb"), _
                           provider, compileUnit)
    ' Use same compile unit to generate C# Hello World
    provider = New Microsoft.CSharp.CSharpCodeProvider
    GenerateViaCodeDOM(IO.Path.Combine(outputDir, _
                           "HelloWorldViaCodeDOM.cs"), _ 
                           provider, compileUnit)

    ***********************

    NOTE BuildGraph is the template that creates the CodeDOM graph and is shown in the next section “Creating the Template.”

    The GenerateViaCodeDOM method contains generic code to process any compile unit. You can call this method multiple times, with different providers to generate code in different languages. The GenerateViaCodeDOM method creates a .NET CodeGenerator from the CodeDOM provider you pass. Like the CodeDOM provider, the CodeDOM generator is language specific:

    Private Shared Sub GenerateViaCodeDOM( _
        ByVal outputFileName As String, _
        ByVal provider As CodeDom.Compiler.CodeDomProvider, _
        ByVal compileunit As CodeDom.CodeCompileUnit)
    Dim gen As CodeDom.Compiler.ICodeGenerator = _
        provider.CreateGenerator()

    The GenerateViaCodeDOM method also creates an IndentedTextWriter to contain the output code. You’ll see more about the IndentedTextWriter later in this chapter and in Chapter 3, but it allows easy control of horizontal whitespace in the output. The IndentedTextWriter wraps a stream, and writing to a stream gives you flexibility in how you later use the generated code:

    Dim tw As CodeDom.Compiler.IndentedTextWriter

    Try
    tw = New CodeDom.Compiler.IndentedTextWriter_
          (New IO.StreamWriter( _ outputFileName, False), " ")

    Once you have everything ready, outputting code is a single call to the GenerateCodeFromCompileUnit method of the code generator. This example uses a new CodeGeneratorOptions object with the default values for generator options:

    gen.GenerateCodeFromCompileUnit(compileunit, tw, _ 
                     New CodeDom.Compiler.CodeGeneratorOptions)

    The remainder of the method handles cleanup in a Finally block that ensures you flush and close the stream before leaving the method:

      Finally
        If Not tw Is Nothing Then
          tw.Flush
          tw.Close()
        End If
      End Try

    End Sub

    Creating the Template

    Generating code in multiple languages is cool, no doubt, but you should consider the cost. Just how hard is it to create the CodeDOM graph for something as simple as the “Hello World” program? The HelloWorldViaCodeDOM.BuildGraph method creates a CodeDOM graph (a CodeCompileUnit) and returns it for further processing:

    ' Class Summary: Hello World via the CodeDOM

    Public Class HelloWorldViaCodeDOM

    #Region "Public Methods and Properties" Public Shared Function BuildGraph() As CodeDom.CodeCompileUnit Dim CompileUnit As New CodeDom.CodeCompileUnit

    A CodeDOM graph always starts with a collection of namespaces. Each namespace contains Imports or C#’s using statements, comments, and types:

    Dim nSpace As New CodeDom.CodeNamespace("HelloWorldViaCodeDOM") CompileUnit.Namespaces.Add(nSpace) nSpace.Imports.Add(New CodeDom.CodeNamespaceImport("System"))

    Types can be structures, enums, delegates, classes, and so on. This code creates a type that’s a class named Startup and adds it to the namespace:

    Dim clsStartup As New CodeDom.CodeTypeDeclaration("Startup") nSpace.Types.Add(clsStartup)

    Types contain members. Members can be fields,2 methods, properties, and so on. You can specify different details depending on the member category, such as an initial value for fields or a collection of statements for methods. CodeEntryPointMethod is a member of the Startup class that specifies a method used to start up the application:

    Dim main As New CodeDom.CodeEntryPointMethod

    So far, the CodeDOM requires extra work, but the approach is logical and intuitive.

    ***************

    2. Class-level variables are also called fields.

    Building individual statements is the difficult and probably nonintuitive part of using the CodeDOM. You separately create each piece of the statement—each variable, literal expression, operator, invocation, and so on. Variables are created for the literal “Hello World,” for the reference to the console class, and for the invocation of the WriteLine method using these two variables. Once you have the statement created, you add it to the statement collection of the method:

    Dim exp As New CodeDom.CodePrimitiveExpression("Hello World!") Dim refExp As New CodeDom.CodeTypeReferenceExpression("System.Console") Dim invoke As New CodeDom.CodeMethodInvokeExpression( _

    refExp, "WriteLine", exp) main.Statements.Add(New CodeDom.CodeExpressionStatement(invoke))

    clsStartup.Members.Add(main)

    Return CompileUnit End Function #End Region

    End Class

    Whew! Some of that didn’t look too bad, but there are four lines of weird code for the one line of output:

    Console.WriteLine("Hello World")

    And, yes, you have to write code like that for almost every line of .NET code in your target file—and, yes, it gets worse with less simplistic code. That’s the core of why the CodeDOM is hard. By abstracting to this detailed level, it’s hard to read the template to predict the output, and you can’t search in it. Even worse, it isn’t going to produce the same output. Some things require extra work, sometimes with poorly documented features. For example, vertical whitespace, VB .NET option statements, and regions are all difficult or impossible to produce via the CodeDOM.

    It’s easy to see why you have to work with this complete abstraction to meet a goal of complete language independence. The generator slams these fragments together quite differently to build code in the different languages. This stuff gets really sticky as the complexity increases. There are 74 classes in the CodeDOM namespace itself as well as many additional classes in the CodeDOM.Compiler name-space. The CodeDOM is workable only for programmers who are tenacious, deal well with abstractions, and have plenty of time. 

    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.

     

    More .NET Articles
    More By Apress Publishing


     

    .NET ARTICLES

    - More on Commands, Input and the WPF
    - Grouping and Aggregating When Querying LINQ ...
    - Commands, Input and the WPF
    - Keyboard and Ink Input with WPF
    - Mouse Input and the WPF
    - Input with Windows Presentation Foundation
    - Introducing LINQ with XML and Databases
    - An Introduction to LINQ
    - Querying LINQ to SQL: Basics
    - Completing a Simple Storefront with LINQ
    - Knowing Your Environment: the System.Environ...
    - Creating the Home Page for a Simple Storefro...
    - LINQ Quickly with Language Integrated Queries
    - Introducing LINQ to SQL Designer using Visua...
    - Beginning LINQ to SQL Using Visual Studio 20...





    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 2 hosted by Hostway