Template Code Generator Examples
The template code generator adds basic C++ “template”
functionality to C#. It can also be used
as a tool to provide generics support to C# until generics are added at a later
date.
There are two parts to using the template code generator. Firstly, you need to specify a template definition. The template definition is the code used to
define what the template target region
(target region) is expanded to. The
target region, therefore, is the section of code that contains the expanded
code and the template definition contains the code that will be expanded into
the target region.
To obtain generics support you need to place your template
definitions in a template definition file. Given these template definitions you can add target
regions to your C# source code file. Once
these two steps have been completed you can expand the source code files with
the template definitions by running the tcg.exe
command prior to compiling your source code.
When the tcg.exe command is
executed, it will parse through the C# file, find all the template target
regions and then expand those regions with the templatized
code. The templatized
code, therefore, it inserted back in to the original
C# file.
For example, consider the simple case in which you want to
create a template for properties within you class. You want the end result to be as follows:
public float
MyFloat
{
get
{
return m_MyFloat;
}
set
{
m_MyFloat
= value;
}
}
private float
m_MyFloat;
However, since you have many different properties with a
similar structure, you decide to create a template for the property. The template not only saves you from copying
the original source but allows you to change all the template target regions at
once by updating the template target region.
To define a template you create a new text file that has the
CST extension (the extension is arbitrary but CST is generally the convention.). Inside the new text file you place the
template code as follows:
#region
template Propv(dataType, typeName)
public dataType
typeName
{
get
{
return m_##typeName;
}
set
{
m_##typeName
= value;
}
}
private dataType
m_##typeName;
#endregion template
The #region template
and #endregion
template are the tags that identify the code that makes up the template
definition. The Propv is the name of the
template while the parameters following the name, dataType and typeName
are the parameters.
When the template code generator runs it creates a list of
all the template definitions found within the template definition files. Next, the template code generator searches
through the C# source code files for all the template target regions. A region is identified by begin and end tags
such as in the example below:
#region
template Propv(dataType, typeName)
#endregion template
What appears between the header (#region template Propv(dataType, typeName))
and footer (#endregion
template) of the template target region is entirely irrelevant as it is
replaced during the run of the template code generator. After the template code generator has
finished the C# source code files will each be updated with the expanded
template target regions such as in the example below:
#region
template Propv(float, MyFloat)
public float
MyFloat
{
get
{
return m_MyFloat;
}
set
{
m_MyFloat
= value;
}
}
private float
m_MyFloat;
#endregion template
The tcg.exe program
is expected to be run from the command line or the pre-build event within
Visual Studio.NET 2003.
Syntax:
Tcg.exe [/help | /?] /t:<templateFileNames> <FileName1> <FileName2> …
· /help will show the help menu.
· /? will show the help menu.
· /t:<templateFileNames> are the template files that should be used to look for template definitions. This list can be comma-seperated, but must not contain any spaces unless enclosed in quotes.
· Filenames are the C# files that are to be expanded with the templates. This list should be space separated.
· For filenames, full wildcard support is available
e.g.
tcg.exe /t:*.cst *.cs
· This would run the template code generator on all C# files using all the defined templates. One thing to note is that the Template Code Generator has a default directory where it looks for templates and when this syntax is used, all the files in the default directory will be searched as well for possible template expansions. If the template definition cannot be found locally, it will use the definition in the default directory. Of course, if the template definition can be found locally, the local definition takes priority over the default template definitions.
tcg.exe /t:<templateName> <C#File1Name> <C#File2Name>
· This causes the template code generator to only operate on the two C# files that were passed in. It will also limit its template definition search to the specified template file and it will look in the default template directory for a file with the same name as well. If a filename is passed into the template declaration (a *.cst) is not used, then only those particular files passed in will be searched for locally AND in the default directory.
There is also an AddIn that has
been created that will expand the #region template right when it is
defined. Upon typing a valid begin region
for a template and pressing <Enter>, the Template Code Generator will
search the Template Definitions that have been defined and try to expand the
Template Region. If no definition is
found, an associated end tag will be entered, but the body will not be
expanded. The template files that are
searched for possible matching definitions are the template files defined in
the Default Templates directory, as well as all local templates that are
defined inside the current project that contains the c-sharp file that is
currently being edited.
Known Issues
·
The IDE currently acknowledges a change to a
line (even an existing line) as a NewLine which will
cause some problems with the AddIn occasionally. If this happens, you just need to modify the
code inside of the template region. From
what I have seen, there is at most one line of code that gets added that will
need to be deleted. This bug is known by
the Framework team and will be looked at.
·
If a change is made to the #region template tag,
make sure you move to the end of the line before you press <Enter> or
move your cursor off the line. If you
don’t do this, you will have the same issues that happens
above.
·
When running the build from within the IDE, you
need to close down all files that have template regions defined in them. If you do not do this, you will need to
compile your code twice due to a bug that has been sent to Microsoft with their
IDE.
C-Sharp File Example
using System;
using System.Collections;
namespace Itron.Tools.TemplateCodeGenerator.Test.TestFiles
{
#region PropvTestHeader
//************************************************************
// Type Name: PropvTest
/// <summary>
/// Summary description for PropvTest.
/// </summary>
///
/// <remarks></remarks>
///
/// <authorInitials>MAS</authorInitials>
/// <creationDate>
//************************************************************
#endregion PropvTestHeader
public class
PropvTest
{
#region PROPERTIES
#region template Propv(public, float, MyFloat)
#endregion template
#region template Propv(protected, int, MyInt)
#endregion template
#region template Propv(private, ArrayList, MyArrayList)
#endregion template
#endregion PROPERTIES
#region METHODS
public PropvTest()
{
//
// TODO: Add constructor
logic here
//
}
#endregion METHODS
}
}
Template Definition Example
#region template Propv(scope, dataType, typeName)
[System.Diagnostics.DebuggerStepThroughAttribute()]
scope dataType
typeName
{
get
{
return m_##typeName;
}
set
{
m_##typeName = value;
}
}
private dataType
m_##typeName;
#endregion
template
#region template Propv(dataType, typeName)
[System.Diagnostics.DebuggerStepThroughAttribute()]
public dataType
typeName
{
get
{
return m_##typeName;
}
set
{
m_##typeName = value;
}
}
private dataType
m_##typeName;
#endregion template
Expanded C-Sharp
File
using System;
using System.Collections;
namespace Itron.Tools.TemplateCodeGenerator.Test.TestFiles
{
#region PropvTestHeader
//************************************************************
// Type Name: PropvTest
/// <summary>
/// Summary description for PropvTest.
/// </summary>
///
/// <remarks></remarks>
///
/// <authorInitials>MAS</authorInitials>
/// <creationDate>January 23,
2003</creationDate>
//************************************************************
#endregion PropvTestHeader
public class PropvTest
{
#region PROPERTIES
#region template Propv(public,
float, MyFloat)
[System.Diagnostics.DebuggerStepThroughAttribute()]
public float MyFloat
{
get
{
return m_MyFloat;
}
set
{
m_MyFloat = value;
}
}
private float m_MyFloat;
#endregion template
#region template Propv(protected,
int, MyInt)
[System.Diagnostics.DebuggerStepThroughAttribute()]
protected int MyInt
{
get
{
return m_MyInt;
}
set
{
m_MyInt = value;
}
}
private int m_MyInt;
#endregion template
#region template Propv(private,
ArrayList, MyArrayList)
[System.Diagnostics.DebuggerStepThroughAttribute()]
private ArrayList MyArrayList
{
get
{
return m_MyArrayList;
}
set
{
m_MyArrayList =
value;
}
}
private ArrayList m_MyArrayList;
#endregion template
#endregion PROPERTIES
#region METHODS
public PropvTest()
{
//
// TODO: Add constructor logic here
//
}
#endregion METHODS
}
}