[Source: http://geekswithblogs.net/EltonStoneman]

I’ve been working on a Guidance package which lets you use Visual Studio as a front end to generate items from T4 templates. Using a recipe wizard you choose your metadata from a Web service, database or file system source, and the template is rendered against each of the metadata objects you select. It’s on CodePlex here: Code Generation Guidance Package, and comes in two flavours. The basic Guidance package has a single recipe “Add generated items” – when you run it, you specify a metadata provider, select the items to use for metadata and the T4 template to render against the items.

The second package is a sample which extends the functionality of the main Guidance package with custom recipes. This demonstrates how you can define recipes for pre-configured generation types, so the user does not need to complete all the wizard pages – one example specifies a database connection string and a T4 template for generating stored procedure wrappers; to add a new DAL class, the user runs the recipe and just selects which stored procedure(s) they want generated.

Neither package comes with any Visual Studio solution or project templates, and they do not need to be used to create the original solution. Any existing project can make use of the code generation features by enabling the package(s) through ToolsGuidance Package Manager.

In this post I’ll give an overview of using the basic Sixeyed.Guidance.CodeGeneration package, and in future posts I’ll add some technical detail and give a walkthrough of the sample project.

Add Generated Items

Run the Add generated items recipe from the Guidance Package Manager, or from the context menu of any project in Solution Explorer. The wizard loads to collect settings – in the first page you select the metadata source type, configure the source and select the metadata provider:

During generation, the provider will load each of the selected metadata items and provide them as a property which can be accessed in the T4 template. For instance if you use the SQL Server Stored Procedure provider, your T4 script will have a populated SqlCommand object available to use.

Provided with the basic Guidance package are the following Sources and Providers:

  • File System
    • File source – for using one or more files as metadata
      • XML File provider – for using XML file contents, exposed to the template as an XmlDocument instance
      • Text File provider – for using text file contents, exposed as a string
      • Assembly File provider – for using a .NET assembly, exposed as an Assembly instance
    • Directory source – for using a list of directory contents as metadata
      • File List provider – for using a list of file names, exposed as a List<string> instance
      • Directory provider – for using a directory, exposed as a DirectoryInfo instance
  • Database
    • SQL Server Database
      • Query Result provider – for executing a SQL query and exposing the results in a populated DataSet
      • Table provider – for using a table as metadata, exposed as an empty DataTable with the correct structure
      • Stored Procedure provider – for using stored procedures, exposed as a populated SqlCommand object
  • WSDL
    • SOAP source
      • Web Method provider – for using a Web service method, exposed as a MethodInfo object
      • Schema provider – for using the WSDL of the service, exposed as an XmlSchema object

When you select a provider, it will load a list of all available metadata items, and you select which items you want to run the T4 template against:

The item selection is always a simple list displaying the item name – this will be the name of the file, table, Web method etc (an exception is the QueryResult provider which uses this page to capture the SQL query to be executed).

In the final screen, select the T4 template to use:

The file dialog will default to the “Templates” folder of the Guidance package, but you can navigate to any T4 file. If you want to override the output settings from the T4 file, specifying a different target filename, namespace extension or class name you can do it in the additional properties in this step:

Finish the wizard and the recipe will iterate over each of the selected items, populating a representation of the metadata and passing it to the T4 template property.

T4 Template Properties

In order to access metadata item information and create the output, your T4 script needs to specify two properties which will be populated using the Guidance PropertyProcessor engine:

<#@ property processor=”PropertyProcessor” name=”MetadataItem” #>

<#@ property processor=”PropertyProcessor” name=”TemplateConfiguration” #>

The MetadataItem property is an object implementing Sixeyed.CodeGeneration.Metadata.Interfaces.IMetadataItem:

The underlying Item property gives you access to the populated metadata item – the object type will depend on the provider, and will be specified in the ItemType property. The Key for the item (the name shown in the Select Items wizard page) is available, as is the metadata Provider which can be used to navigate up to the source.

The TemplateConfiguration property allows you to control the output of the template, setting default values for the target file name etc. (which can be overridden in the Select Template wizard page). It’s an object of type Sixeyed.CodeGeneration.Generation.TemplateConfiguration:

Sample Templates

The CodeGeneration.Sample Guidance package contains a sample template for each of the metadata providers, demonstrating the type of object they expose and how it can be used. The scripts don’t do much other than demonstrate usage, but there are fully-fledged scripts for generating wrappers for SQL Server stored procedures, and configuration sections from text files. The full script for the Table provider sample makes straightforward use of the underlying DataTable object:

<#@ template language=C# #>

<#@ property processor=PropertyProcessor name=MetadataItem #>

<#@ property processor=PropertyProcessor name=TemplateConfiguration #>

<#@ assembly name=System.dll #>

<#@ assembly name=System.Data.dll #>

<#@ assembly name=System.Xml.dll #>

<#@ assembly name=Sixeyed.CodeGeneration.dll #>

<#@ import namespace=System.Data #>

<#@ import namespace=Sixeyed.CodeGeneration.Generation #>

<# PrepareOutput(); #>

/*

Table name (from metadata): <#= MetadataItem.Key #>

Table name (from table): <#= dataTable.TableName #>

Columns:

<# foreach (DataColumn column in dataTable.Columns)

{

#>Column Name: <#= column.ColumnName #>

Data Type: <#= column.DataType #>

<#} #>

*/

<#+

private DataTable dataTable

{

get{ return MetadataItem.Item as DataTable; }

}

private void PrepareOutput()

{

TemplateConfiguration.ClassName = string.Format(“Table_{0}”, MemberName.ToPascalCase(MetadataItem.Key, true));

TemplateConfiguration.FileExtension = “cs”;

}

#>

(If you don’t already have it, the T4 Editor Community Edition from Clarius makes editing templates much easier).

The directives specify the expected properties, and import the relevant reference assemblies and namespaces. The script provides the dataTable property to easily access the metadata item as a typed DataTable object. In the PrepareOutput method (called at the start of the template), the script sets up the target class name and file extension. In this case a target filename is not specified, so the engine will use the class name and file extension for the filename. Note there are some helper methods in Sixeyed.CodeGeneration.Generation.MemberName for preparing valid member names.

Selecting a single table called Manufacturers for this script generates and adds a file called Table_Manufacturers.cs to the selected project, containing the following output:

/*

Table name (from metadata): Manufacturers

Table name (from table): Manufacturers

Columns:

Column Name: ManufacturerId

Data Type: System.Int16

Column Name: ManufacturerName

Data Type: System.String

Column Name: AvailableFromDate

Data Type: System.DateTime

Column Name: AvailableToDate

Data Type: System.DateTime

*/

Usage

For ad-hoc code generation, this basic Guidance package lets you specify metadata to execute against a T4 template. For commonly used scripts and standard patterns you can build a custom Guidance package which contains your solution structure, and specific recipes for generating known types of item – for DAL classes, entities, configuration sections, proxies or anything else that is based on external metadata.