Tip
Our use of CodeSmith is not designed as a full tour of the product.We recommend you gain some
familiarity with the IDE before continuing.
You can hook up the navigator to the CodeGenfolder in the source code for this chapter to
begin working with the following examples.
Using Properties
Using CodeSmith, we can very easily produce a template that accepts a parameter and pro-
duces some arbitrary output. Consider the following template:
<%-- 
Name:         test.single.cst
Author:       Marc Holmes
Description:  Generates a file with a single variable.
%>
CHAPTER 9 ■ CODE GENERATION
283
Figure 9-1.The CodeSmith IDE
Convert pdf pages to jpg - Convert PDF to JPEG images in C#.net, ASP.NET MVC, WinForms, WPF project
How to convert PDF to JPEG using C#.NET PDF to JPEG conversion / converter library control SDK
batch convert pdf to jpg; best convert pdf to jpg
Convert pdf pages to jpg - VB.NET PDF Convert to Jpeg SDK: Convert PDF to JPEG images in vb.net, ASP.NET MVC, WinForms, WPF project
Online Tutorial for PDF to JPEG (JPG) Conversion in VB.NET Image Application
pdf to jpeg converter; advanced pdf to jpg converter
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits=""
Debug="False" Description="Generates a file with a single variable." %>
<%@ Property Name="SolutionName" Type="System.String" Default="Etomic.Test" 
Optional="False" Category="Project" Description="The project name " %>
This file generated by CodeSmith on <%= DateTime.Now.ToLongDateString() %>
Name: <%=SolutionName%>
When executed using Etomic.Test.1as the SolutionNameproperty (the type is set to
System.String), the following output is observed:
This file generated by CodeSmith on 17 January 2005
Name: Etomic.Test.1
So this is perfectly acceptable where we need only enter single property values to handle
the transformation, but in fact we have multiple values for the same property (as we have
multiple solutions). We cannot run CodeSmith multiple times since all of the solutions need
to be in the same file for the ccnet.configfile.
The following template file demonstrates the use of a collection as a property:
<%-- 
Name:         test.multiple.cst
Author:
Marc Holmes
Description:  Generates a file with multiple variables.
%>
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits=""
Debug="False" Description="Generates a file with multiple variables." %>
<%@ Property Name="SolutionNames" Type="System.String[]" Default="Etomic.Test" 
Optional="False" Category="Project" Description="The project name" %>
This file generated by CodeSmith on <%= DateTime.Now.ToLongDateString() %>
<%
foreach(string SolutionName in SolutionNames)
{
%>
Name: <%=SolutionName%>
<%
}
%>
In this instance I have used a string array—CodeSmith can handle most framework types
automatically—to maintain the list of solution names. I can then use some C# to loop through
the array and produce output for each value in the array. When we try to input the array for
this template, the property editor identifies the need for a collection editor and produces the
screen shown in Figure 9-2.
CHAPTER 9 ■ CODE GENERATION
284
C# Image Convert: How to Convert Adobe PDF to Jpeg, Png, Bmp, &
C# sample code for PDF to jpg image conversion. This demo code convert PDF file all pages to jpg images. // Define input and output files path.
changing pdf to jpg file; convert pdf image to jpg online
C# Image Convert: How to Convert Tiff Image to Jpeg, Png, Bmp, &
RasterEdge.XDoc.Office.Inner.Office03.dll. RasterEdge.XDoc.PDF.dll. This demo code convert TIFF file all pages to jpg images.
batch pdf to jpg online; convert pdf to jpeg on
Figure 9-2.Collection editing in CodeSmith
The resulting output looks like this:
This file generated by CodeSmith on 17 January 2005
Name: Etomic.Test.1
Name: Etomic.Test.2
This is much closer to our desired use of CodeSmith. There are more complicated require-
ments, however: the need to use XML as the input to CodeSmith, and the need to output
multiple files.
Fortunately, both of these issues are handled neatly by CodeSmith with a little work on
our part. The code used in the following solutions is lifted from the samples that come with
CodeSmith and is repurposed for my specific needs here.
First, we must use an XML file for input. Consider the following very basic XML file that
we might want to use to maintain the master information:
<?xml version="1.0"?>
<ProjectSet xmlns="http://www.etomic.co.uk">
<Projects>
<Project Name="Etomic.Test.1"/>
<Project Name="Etomic.Test.2"/>
</Projects>
</ProjectSet>
At the moment, this is no more complicated than the string array from the earlier example,
but of course this schema can be extended. CodeSmith can handle the input of such a file
through the creation of two things: an XML-serializable type and a suitable property editor.
Fortunately, CodeSmith comes with the appropriate XmlSerializedFilePickercontrol and
sowe just need to reference and utilize the control.
CHAPTER 9 ■ CODE GENERATION
285
C# Create PDF from images Library to convert Jpeg, png images to
Batch convert PDF documents from multiple image formats, including Jpg, Png, Bmp, Gif, Tiff, Bitmap, .NET Graphics, and REImage.
convert pdf file to jpg format; batch pdf to jpg converter
VB.NET PDF Convert to Images SDK: Convert PDF to png, gif images
Resize converted image files in VB.NET. Convert PDF to Jpg, Png, Bmp, Gif, Tiff and Bitmap in ASP.NET. Embed PDF to image converter in viewer.
convert pdf to jpg for online; bulk pdf to jpg
The following code could be used to handle the above XML file:
using System;
using System.Xml.Serialization;
using System.ComponentModel;
using CodeSmith.CustomProperties;
namespace Etomic.CodeSmithExtensions.BuildAutomation
{
[TypeConverter(typeof(XmlSerializedTypeConverter))]
[Editor(typeof(CodeSmith.CustomProperties.XmlSerializedFilePicker),
typeof(System.Drawing.Design.UITypeEditor))]
[XmlRoot("ProjectSet", Namespace="http://www.etomic.co.uk", IsNullable = false)]
public class ProjectSet
{
[XmlArray("Projects")]
public Project[] Projects;
}
public class Project
{
[XmlAttribute]
public string Name;
}
}
The boldfaced code here references the aforementioned control and a converter for the
XML file. In order to use these, the following assemblies must be referenced in the project:
CodeSmith.CustomProperties.dllandCodeSmith.Engine.dll.
The other attributes in this example configure the XML-serializable types needed for the
XML (or vice versa!). This is a trivial example: ProjectSetcontains a collection of projects.
Aprojecthas a single attribute: name.
If you compile this assembly and place it in the CodeSmith folder along with the other
CodeSmith assemblies, then the following template can be assembled.
Tip
It seems to be easier to place the additional CodeSmith assemblies in the main CodeSmith folder.
Iobtained several access errors when attempting to use the extensions from other areas—even those
“approved”by CodeSmith.
<%-- 
Name:         test.xml.cst
Author:       Marc Holmes
Description:  Generates a file with an XML file input.
%>
CHAPTER 9 ■ CODE GENERATION
286
VB.NET PDF - Convert PDF with VB.NET WPF PDF Viewer
Create multiple pages Tiff file from PDF document. Convert PDF to image file formats with high quality, support converting PDF to PNG, JPG, BMP and GIF.
.net pdf to jpg; change pdf into jpg
C# TIFF: C#.NET Code to Convert JPEG Images to TIFF
Use C# Code to Convert Jpeg to Tiff. string[] imagePaths = { @"C:\demo1.jpg", @"C:\demo2.jpg", @"C:\demo3.jpg" }; // Construct List<REImage> object.
batch pdf to jpg; convert pdf photo to jpg
<%@ CodeTemplate Language="C#" TargetLanguage="Text" 
Description="Generates a file with an XML file input." %>
<%@ Assembly Name="Etomic.CodeSmithExtensions.BuildAutomation" %>
<%@ Property Name="ProjectSet"
Type="Etomic.CodeSmithExtensions.BuildAutomation.ProjectSet" 
Description="The XML file containing the project definitions." %>
Name: <%=ProjectSet.Projects[0].Name%>
In this template an additional directive is needed: the assemblydirective. This instructs
CodeSmith to load the extension assembly, which would not occur by default, so that it can be
used in the template. Subsequently, the property ProjectSetcan be typed to the ProjectSet
type within the extension assembly. Finally, we can use the type as we might expect to in
C#code. 
When we use the properties window to select the XML file, the correct property editor is
chosen thanks to the declarative code attributes in the ProjectSettype. The CodeSmith win-
dow appears as shown in Figure 9-3 at this point.
CHAPTER 9 ■ CODE GENERATION
287
Figure 9-3.Editing the XML selection
C# WPF PDF Viewer SDK to convert and export PDF document to other
Create multiple pages Tiff file from PDF document. Convert PDF to image file formats with high quality, support converting PDF to PNG, JPG, BMP and GIF.
convert pdf image to jpg; .pdf to .jpg online
VB.NET Create PDF from images Library to convert Jpeg, png images
Components to batch convert PDF documents in Visual Basic .NET class. Support create PDF from multiple image formats in VB.NET, including Jpg, Png, Bmp, Gif
change file from pdf to jpg on; convert from pdf to jpg
Once the desired XML input file is selected and the template is executed, the output is as
expected:
This file generated by CodeSmith on 17 January 2005
Name: Etomic.Test.1
At the moment, the ProjectSettype is very simple, but we can extend it as required.
Wewill explore this further as we begin the real work in earnest. There is still one more issue,
however.
Generating Multiple Files
The examples so far have generated only one file. Once again, there is a fairly simple code-
based method for generating multiple output files. Bear in mind that we will also need to
tackle this issue using XSLT in a little while.
TheTestOutputsfolder in the source code for Chapter 9 contains four templates. The first
three—ccnet.cst,build.cst, and deploy.cst—are simply placeholders for what will be the
delivery scripts, but they are needed to test the example. The fourth—master.cst—contains
the code that handles the multiple outputs.
The CodeSmith API can be used to perform the actions we need. First, the declarative
code is as follows:
<%-- 
Name:         master.cst
Author:       Marc Holmes
Description:  Creates all required outputs for the build automation.
%>
<%@ CodeTemplate Language="C#" TargetLanguage="Text" Src="" Inherits="" ➥
Debug="False" Description="Creates required outputs for the build automation." %>
<%@ Assembly Name="Etomic.CodeSmithExtensions.BuildAutomation" %>
<%@ Assembly Name="System.Design" %>
<%@ Import NameSpace="System.IO" %>
<%@ Property Name="ProjectSet" 
Type="Etomic.CodeSmithExtensions.BuildAutomation.ProjectSet"
Description="The XML file containing the project definitions." %>
We are loading in the extension assembly as before since this is the master template, and
therefore the template will supply variables too. Additionally, because we will be producing
file-based output, we import the System.IOnamespace. We are also going to use a “folder
picker” dialog box, which requires the loading of the System.Designassembly. The output➥
Directoryproperty is provided as follows:
private string _outputDirectory = String.Empty;
[Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), ➥
typeof(System.Drawing.Design.UITypeEditor))] 
[CodeTemplateProperty(CodeTemplatePropertyOption.Optional)]
CHAPTER 9 ■ CODE GENERATION
288
[Category("Output")]
[Description("The directory to output the results to.")]
public string OutputDirectory 
get
{
if (_outputDirectory.Length == 0) return ➥
this.CodeTemplateInfo.DirectoryName + "output";
return _outputDirectory;
}
set
{
if (value.EndsWith("\\")) value = value.Substring(0, value.Length - 1);
_outputDirectory = value;
}
This property ensures that a folder picker dialog box is used in the property editor to
select the output folder, though in fact the property is a string. A little tidying is performed in
the getter and setter for the property.
The next two methods required for the template are lifted from the CodeSmith documen-
tation and massaged to our needs:
public CodeTemplate CompileTemplate(string templateName)
{
CodeTemplateCompiler compiler = new CodeTemplateCompiler(templateName);
compiler.Compile();
if (compiler.Errors.Count == 0)
{
return compiler.CreateInstance();
}
else
{
for (int i = 0; i < compiler.Errors.Count; i++)
{
Response.WriteLine(compiler.Errors[i].ToString());
}
return null;
}
}
public CodeTemplate GetTemplate(string templateName)
{
return this.CompileTemplate(this.CodeTemplateInfo.DirectoryName + ➥
templateName);
}
CHAPTER 9 ■ CODE GENERATION
289
Essentially, these two methods allow the loading of template files, followed by the compi-
lation of the template. The template file then exists as a CodeTemplatetype with its own set of
methods and properties. 
Next is the code required to perform the actions we will be looking for: we want to pro-
duce a single ccnet.configfile containing all project information, and a single build file and
deploy file per project in order to replicate the standards already in place. We need the other
three code template files to do this. They will be held in the following code:
private CodeTemplate _ccnetTemplate;
private CodeTemplate _buildTemplate;
private CodeTemplate _deployTemplate;
The main method for the template is as follows:
public void Go()
{
DateTime startTime = DateTime.Now;
Response.WriteLine("Beginning generation...");
_ccnetTemplate = this.GetTemplate("CCNet.cst");
_buildTemplate = this.GetTemplate("Build.cst");
_deployTemplate = this.GetTemplate("Deploy.cst");
_buildTemplate.SetProperty("ProjectSet", ProjectSet);
_deployTemplate.SetProperty("ProjectSet", ProjectSet);
for(int i = 0; i < ProjectSet.Projects.Length; i++)
{
Response.WriteLine("Preparing Build for " + ➥
ProjectSet.Projects[i].Name);
_buildTemplate.SetProperty("ProjectNumber", i);
_buildTemplate.RenderToFile(OutputDirectory + "\\" + 
ProjectSet.Settings["CompanyName"] +"." +ProjectSet.Projects[i].Name 
+".Build.xml", true);
Response.WriteLine("Preparing Deploy for " + ➥
ProjectSet.Projects[i].Name);
_deployTemplate.SetProperty("ProjectNumber", i);
_deployTemplate.RenderToFile(OutputDirectory + "\\" + ➥
ProjectSet.Settings["CompanyName"] +"." +ProjectSet.Projects[i].Name ➥
+".Deploy.xml", true);
}
Response.WriteLine("Preparing CCNet...");
_ccnetTemplate.SetProperty("ProjectSet", ProjectSet);
_ccnetTemplate.RenderToFile(OutputDirectory + "\\ccnet.config", true);
CHAPTER 9 ■ CODE GENERATION
290
Response.WriteLine("Generation complete. Execution time: " + ➥
(DateTime.Now - startTime).ToString());
Response.WriteLine("To view the output go here: " + OutputDirectory);
}
This code handles everything necessary to produce the output files we require. The most
interesting points are as follows:
The template members are loaded and compiled using the helper functions (for example,
ccnet.cst).
The relevant properties on the child templates are set as required. In the case of these
templates, the ProjectSetproperty is passed through to each child template. Additionally
for the build and deploy templates, the index of the relevant project is passed through.
With the parameters set, the RenderToFilemethod can be called to save the output to the
appropriate location, with the appropriate name.
In the case of the build and deploy files, the project collection is looped through so that
an output file is rendered separately for each project.
Finally, in order to kick off the execution of this template, the following (very ASP-like)
code is added at the bottom of the master template as the entry point:
<%
this.Go();
%>
This template can then be executed by selecting a relevant output directory (or leaving it
blank to accept the default) and the relevant XML input file. The output from the master tem-
plate (to the screen) looks like this:
Beginning generation...
Preparing CCNet...
Preparing Build for Etomic.Test.1
Preparing Deploy for Etomic.Test.1
Preparing Build for Etomic.Test.2
Preparing Deploy for Etomic.Test.2
Generation complete. Execution time: 00:00:00.6093750
To view the output go here: D:\dotNetDelivery\Chapter9\CodeGen\TestOutputs\Output
Reviewing the output folder reveals the files shown in Figure 9-4.
Figure 9-4.The output folder
CHAPTER 9 ■ CODE GENERATION
291
These files look very familiar! They do not contain any interesting information yet, but the
scaffolding needed to begin the real work is complete.
Investigating XSLT
Of course, with XSLT then there is no IDE to investigate, but there is a complex toolset to
understand. Have a look at “Further Reading” for some suggested material.
We took some time to look at the capabilities of the CodeSmith IDE, before we began to
look at some coding to support the delivery processes. In a moment we are going to look at
specific CodeSmith templates to provide the code generation, and also XSLT templates to do
the same. There is one area where we also need to provide some framework code to aid the
use of XSLT: a processor to output multiple files.
Again, the aim is to produce one ccnet.configfile and then one build file and one deploy
file per project. Ordinarily, XSLT will transform one XML file. With a little coding we can gener-
ate the same output as we have seen with CodeSmith.
Ultimately, this code will be used by NAnt to regenerate its own files (we can see this later
on) so we will use a <script>task for this framework code. Let us take a look.
Generating Multiple Output Files with XSLT
To start this work, we will create a separate NAnt file, in this case called Builder.XSLT.xml. The
build file is quite simple, with a single target called XsltBuilderand a call to this target. The
XsltBuildertarget will contain a script task to perform the generation. We saw an example of
this in Chapter 3. 
So the skeleton for Builder.XSLT.xmllooks like this:
<?xml version="1.0"?>
<project>
<target name="XsltBuilder">
<script language="C#">
<imports>
<import namespace="System.Xml"/>
<import namespace="System.Xml.Xsl"/>
<import namespace="System.Xml.XPath"/>
</imports>
<code><![CDATA[
public static void ScriptMain(Project project)
{}
]]></code>
</script>
</target>
<call target="XsltBuilder"/>
</project>
CHAPTER 9 ■ CODE GENERATION
292
Documents you may be interested
Documents you may be interested