Upgrading CodeSmith Generator Templates

We strive to ensure that CodeSmith Generator templates are 100% backwards compatible. However, in very rare circumstances we break backwards compatibility to progress the platform. When we do break backwards compatibility, we ensure that the benefits of breaking compatibility greatly out-way the benefits of not breaking compatibility. Please refer to this document when upgrading CodeSmith Generator to ensure that you have the smoothest experience possible.

Upgrading from all previous versions of CodeSmith Generator

Please read this guide when upgrading from any version of CodeSmith Generator.

Recompiling Template Assembly References

If you have a custom template that references an assembly that references CodeSmith Generator or you are using one of our Template Frameworks (E.G., PLINQO, CSLA...) then please continue reading this step.

When upgrading from any version of CodeSmith Generator, please follow the below steps:

CodeSmith Generator is compiled against version 4.6.2 of the .NET Framework. This means that all code that consumes the Generator API needs to be targeting .NET 4.6.2 or newer. This does not mean that the template you write has to generate .NET 4.0 code (CodeSmith Generator can generate any text based content...)! This just means that your CodeSmith Generator class libraries need to be compiled as .NET 4.6.2.

  1. Locate your templates source code folder or source project and open the Visual Studio solution. The source code for our Template Frameworks can be found in the templates \Source\ directory.
  2. Update all Visual Studio projects that reference CodeSmith.Engine to .NET 4.6.2
  3. Update all of the Visual Studio project's assembly references in your Solution that reference CodeSmith Generator assemblies. Below is a set of steps that will help guide you through this process.
    1. Open Solution Explorer.
    2. Right click on your Project in Solution Explorer and select Add Reference.
    3. The Add References dialog will contain all CodeSmith Generator references. If you do not see the reference in the list, then they can be be found in the Generator Program Files folder.
    4. Select the reference and click the OK button.
  4. Add a project reference to CodeSmith.Core to all Visual Studio projects that reference CodeSmith assemblies. This assembly is located in the CodeSmith Generator Program Files bin folder.
  5. Rebuild your Solution. 

    If you are updating an existing Template Framework Solution. Please ensure that each projects compiled assemblies are being copied to the correct folder after build (E.G., from the \ProjectName\bin\debug folder to the templates \common\ folder).

  6. Regenerate your existing Generator Project Files
The source code for our Template Frameworks can be found in the templates Source directory.

Downloading the latest Templates

CodeSmith Generator ships with the latest version of the templates so there is no need to go out and download the latest set of templates. However, the latest set of templates can be found on the CodeSmith Generator Google Code project.

Please follow the steps below when downloading any template from the internet. Also, please ensure that the template was downloaded from a safe and reliable source, as you are executing code on your system!

The following steps need to be completed before executing the templates! The .NET run-time places security restrictions on code that has been downloaded from the internet or is placed on a network share. As such, you need to follow the steps below.

  1. Download or move the downloaded templates or zip to a non networked share.
  2. Please unblock the zip file before extracting or unblock all assemblies (.dll, .exe) before generating by following the steps below.
    1. Open Windows Explorer and navigate to where the Zip file is saved.

    2. Select the file and right-click on it. On the menu that appears, click on "Properties."
    3. Click on "unblock" in the bottom right-hand corner of the dialog box that appears.
    4. Click on "OK" if you see a Windows warning message. The button with "Unblock" should either become grayed out or disappear.

Updating existing CodeSmith Generator Projects

After upgrading to the latest version of CodeSmith Generator, please ensure that your Generator Project files are up to date. You can do this by opening Manage Outputs and ensuring that the template location points to the latest version of the templates.

Updates to CodeSmith.BaseTemplates.SqlCodeTemplate and CodeSmith.BaseTemplates.VBSqlCodeTemplate

The following virtual methods (GetSqlReaderAssignmentStatement, GetPropertyNameIncludeEmptyCheckGetCSharpVariableType and GetVBVariableType) explicitly checked for columns that end with "TypeCode". If the column ended with "TypeCode", then the returned result would be treated as an enumeration. We've removed this special cased behavior as it can lead to unattended bugs in the generated code. 

This change will effect you if all of the criteria below match:

UITypeEditor deprecation

UITypeEditors are marked as deprecated and will be removed in a future version. The property grid component we use is WPF and no longer supports Windows Forms UITypeEditors going forward. Our recommendation is to use the built in property grid editors.

Transitive Dependencies

All transitive dependencies must be referenced with an assembly directive to the CodeTemplate. The template will fail to compile in certain scenarios like when using the MSBuild integration.

An example of this would be the CodeSmith.BaseTemplates class library references CodeSmith.CustomProperties class library but most existing templates only reference <%@ Assembly Name="CodeSmith.BaseTemplates" %>. The fix is to add all transitive dependencies with an assembly directive <%@ Assembly Name="CodeSmith.CustomProperties" %>.

Upgrading from CodeSmith Generator 6.0

In Generator 6.0, we introduced a new API's to compile templates using TemplateEngine. In Generator 6.5, we made some major improvements to the TemplateEngine, DefaultEngineHost and IEngineHost interface. These changes allowed us to support new features in memory content. It also allowed feature development without breaking the API. The section below covers any breaking changes that were made during these updates.

Updates to IEngineHost interface

Some breaking API changes were made to the DefaultEngineHost to allow for content memory management improvements. We also renamed a few methods to have more generic names. 

Please see the following table for all the changes that have occurred to the interface in the current version.

Generator 6.0Current ImplementationAction To TakeDescription
string GetFileContent(string)string GetContent(string, bool)Rename Method Overloads and add Boolean parameterThe name was changed to represent generic content and not specifically file content.

bool ContentExists(string)Implement MethodImplement method if you are inheriting the IEngineHost interface or wish to override the default behavior.

RegisteredContent RegisteredContentImplement PropertyImplement property if you are inheriting the IEngineHost interface.

Updates to DefaultEngineHost 

Some breaking API changes were made to the IEngineHost interface to allow for content memory management improvements. We also renamed a few methods to have more generic names. For Example: In the future if someone created a DatabaseEngineHost, it wouldn't make sense to call GetFileContent as you are working with database objects.

Please see the following table for all the changes that have occurred to the interface in the current version.

Generator 6.0Current ImplementationAction To TakeDescription
DefaultEngineHost(string)DefaultEngineHost(string)Validate BasePathThe constructor will now throw an ArgumentException if the passed in base path doesn't exist.
RegisterInMemoryContent(string, string)
Method has been removed.See the example below for more information on registering content.

If you were calling DefaultEngineHost.RegisterInMemoryContent as shown below.

var host = new DefaultEngineHost(Path.GetDirectoryName(filePath));
host.RegisterInMemoryContent(filePath, content);

Then you will need to update your code to the following:

var host = new DefaultEngineHost(Path.GetDirectoryName(filePath));
host.RegisteredContent[filePath] = content;

Upgrading from CodeSmith Generator 2.x, 3.x, 4.x, 5.x

Updates to CodeTemplates Validate method

If you are using a custom CodeTemplate that overrode the Validate method as shown below:

public override void Validate() {
}

you will need to update the method signature to the following:

public override System.Collections.Generic.IEnumerable<ValidationError> GetCustomValidationErrors() {
}

After the method signature has been changed, you will need to update the code implementation to return a list of validation errors.

This change ensures that the CodeTemplates State property will always be correct and any exceptions thrown in GetCustomValidationErrors() will not affect the generation process.

Updates to IMergeStrategy.Merge() method signature

If you are using a custom Merge Strategy please update the Merge method signature as shown below:

public string Merge(CodeTemplate context, string sourceContent, string templateOutput) {
   return templateOutput;
}

you will need to update the method signature to the following:

public string public string Merge(CodeSmith.Engine.MergeContext context)
    return context.OutputContent;
}

After the method signature has been changed, you will need to update the code implementation to use the various properties located on the MergeContext.

These changes were made to provide additional information for Merge Strategies (E.G., InsertClass Merge Strategy) as well as additional information to be added to the MergeContext object in the future without breaking the API. 

Template Frameworks like PLINQO have already been updated  for these changes and will not require a recompile!

Encoding changes

Templates are now generated as UTF-8, this change was made to be more consistent with various other editors like Visual Studio. If you wish to have files generate using ascii or a different encoding please set the ResponseEncoding CodeTemplate Directive attribute on your master template before generating. This also ensures that your template output will always be consistent when generating in any culture.

CodeTemplateCompiler changes

The CodeTemplateCompiler was updated in Generator 6.0 to be a proxy around TemplateEngine, the new template compiler, and is 100% backwards compatible in functionality. However, the CodeTemplateCompiler.Cleanup() method has been removed in 6.0. The Cleanup() method was not implemented in all Generator 5.x releases and can be safely removed.

It is recommended to update your existing CodeTemplateCompiler implementation to use TemplateEngine, but this is not required. Please see the SDK documentation for more information.

SchemaExplorer Type Converter changes

The SchemaExplorer Type Converters have been removed and replaced with a single SchemaObjectFactoryTypeConverter object. This new Type Converter handles the conversion for all SchemaExplorer types deriving from SchemaObjectBase or SchemaObjectCollection. If your template code is using a SchemaExplorer Type Converter as shown below it can be safely removed.

[TypeConverter(typeof(SchemaExplorer.TableSchemaCollectionTypeConverter))]

SchemaExplorer TableSchema.Indexes changes

If you are upgrading from a version lower than 5.x, the returned TableSchema.Indexes collection will be sorted for consistency. Previously the primary keys were ordered first.

SchemaExplorer Collection GetEnumerator() changes

The SchemaExplorer API has been updated for the latest version of .NET. The previous version of SchemaExplorer was written on the .NET 1.0 run time and updated over the previous versions. In the current version of CodeSmith Generator, we rewrote SchemaExplorer to take advantage of generics, Linq and many other language features. The new API changes broke some existing templates that were explicitly using the GetEnumerator() method result. Previously, the GetEnumerator() method returned an interface specific to the type you were working with. Below is a break down of what GetEnumerator() previously returned and what currently returned.

Collection NamePrevious GetEnumerator() return typeCurrent GetEnumerator() return type
ColumnSchemaCollectionIColumnSchemaEnumeratorIEnumerator<ColumnSchema>
CommandResultColumnSchemaCollectionICommandResultColumnSchemaEnumeratorIEnumerator<CommandResultColumnSchema>
CommandResultSchemaCollectionICommandResultSchemaEnumeratorIEnumerator<CommandResultSchema>
CommandSchemaCollectionICommandSchemaEnumeratorIEnumerator<CommandSchema>
DataObjectBaseCollectionIDataObjectBaseEnumeratorIEnumerator<DataObjectBase>
DataSourceCollectionIDataSourceEnumeratorIEnumerator<DataSource>
ExtendedPropertyCollectionIExtendedPropertyEnumeratorIEnumerator<ExtendedProperty>
IDbSchemaProviderCollectionIIDbSchemaProviderEnumeratorIEnumerator<IDbSchemaProvider>
IndexSchemaCollectionIIndexSchemaEnumeratorIEnumerator<IndexSchema>
MemberColumnSchemaCollectionIMemberColumnSchemaEnumeratorIEnumerator<MemberColumnSchema>
ParameterSchemaCollectionIParameterSchemaEnumeratorIEnumerator<ParameterSchema>
SchemaObjectBaseCollectionISchemaObjectBaseEnumeratorIEnumerator<SchemaObjectBase>
TableKeySchemaCollectionITableKeySchemaEnumeratorIEnumerator<TableKeySchema>
TableSchemaCollectionITableSchemaEnumeratorIEnumerator<TableSchema>
TabularObjectBaseCollectionITabularObjectBaseEnumeratorIEnumerator<TabularObjectBase>
ViewSchemaCollectionIViewSchemaEnumeratorIEnumerator<ViewSchema>
Updating existing SchemaExplorer Collection GetEnumerator() code

One can update the existing code by changing the template logic that uses the previous interfaces (second column shown above) to the new format.

<% IColumnSchemaEnumerator allTableColumns = SourceTable.Columns.GetEnumerator() %>

To:

<% IEnumerator<ColumnSchema> allTableColumns = SourceTable.Columns.GetEnumerator() %>

Upgrading from CodeSmith Generator 2.x

Please read this guide when upgrading from CodeSmith Generator 2.x. CodeSmith Generator Templates are almost 100% compatible with CodeSmith Generator 2.x templates, there are a couple breaking changes that CodeSmith Generator 2.x users should be aware of when upgrading. You may need to make minor changes to your CodeSmith Generator 2.x templates to have them work perfectly in the latest version of CodeSmith Generator.

CodeTemplate Directives are required

CodeSmith Generator requires every template to have a CodeTemplate directive. The CodeTemplate directive must be the first thing in the file, with the possible exception of template comments.

Changes to template comments

CodeSmith Generator 2.x allowed you to use several formats for template comments that the latest version of CodeSmith Generator does not allow. In particular, these two formats are no longer accepted for template comments:

<% // some template header %>
<%-- some comment %>

In the latest version of CodeSmith Generator, the only acceptable format for template headers and comments is as follows:

<%-- some template header --%>
<%-- some comment --%>

Note that other formats are still valid when you want to include a comment in the generated source code. This is distinct from including a comment in the template that does not appear in the generated code. To generate a C# comment, you still use the format

<% // some C# comment %>

and to generate a VB comment, you still use the format

<% ' some VB comment %>

Register sub-templates declaratively

Although you can still programmatically compile sub-templates, it is more efficient to use the new Register directive instead.