Coding With Fun
Home Docker Django Node.js Articles Python pip guide FAQ Policy

CodeSmith Merge policy


May 25, 2021 CodeSmith


Table of contents


Merge policy

The basic usage used by CodeSmith to generate code through code templates is described earlier, but if you modify the automatically generated code and use the code template to generate code again, the code you modify is lost, and CodeSmith supports a variety of "merges" to fix this problem to preserve the parts you've fixed yourself.

CodeSmith supports three "merge strategies":

However, these policies are primarily for the languages that support Region, and for other languages other languages that may require other methods, such as custom Merge policies, CodeSmith allows the "merge" policy to be extended through CodeSmith.Engine.IMergeStrategy, and one of the reasons I recommend CodeSmith provides a lot of Interfaces are not just a tool, such as in addition to CodeSmith-supported properties, XML properties, you can also customize the property category through CodeSmith.CustomProperties, in addition to CodeSmith-supported data source types (MySQL, Oracle), you can also support new database types or other data types through custom Schema Provider.

InsertRegion policy

InsertRegion, as the name implies, is to define a Region in the source code and then have CodeSmith's auto-generated code insert only into the region, while code CodeSmith outside the zone doesn't touch them, enabling a combination of custom code and auto-generated code.

PreserveRegion policy

PreserveRegion defines multiple regions, and then tells CodeSmith to keep the area code intact, and the automatically created code is added to the outside of those zones, as opposed to InsertRegion.

Here's a borrowed Merge example from CodeSmith to illustrate the basic uses of both strategies:

The first is the InsertRegion policy, which defines a class file, InsertRegionSample.cs

public class InsertRegionsSample
{

    public void SomeCustomMethod()
    {
        // This is my custom code that I want to preserve.
        // I can make changes to it and my changes will
        // not be overwritten.
    }

    #region Sample Generated Region
// This region generated by CodeSmith on Saturday, 12 January 2013
    #endregion
}

It defines a Region called Sample Generated Region, ready for CodeSmith to check in the code, write a simple code template, and insert the current time:

<%@ Template Language="C#" TargetLanguage="C#"   Description="Demonstrates using an InsertRegion merge strategy in C#." %>
// This region generated by CodeSmith on <%= DateTime.Now.ToLongDateString() %>

Then set the Merge policy for the template with the CodeSmith project:

CodeSmith Merge policy

Select the InsertRegion policy, and then set the RegionName to insert.

The generated code is as follows:

public class InsertRegionsSample
{

    public void SomeCustomMethod()
    {
        // This is my custom code that I want to preserve.
        // I can make changes to it and my changes will
        // not be overwritten.
    }

    #region Sample Generated Region
// This region generated by CodeSmith on Saturday, 12 January 2013
    #endregion
}

You can see that CodeSmith inserts code only at Region, and the part outside the Region remains the same.

Similar PreserveRegions policies, code, and templates are defined as follows: PreserveRegionsSample .cs

public class PreserveRegionsSample
{

#region "Custom Region 1"

    // This is a place holder for your custom code.
    // It must exist so that CodeSmith knows where
    // to put the custom code that will be parsed
    // from the target source file.
    // The region name is used to match up the regions
    // and determine where each region of custom code
    // should be inserted into the merge result.

#endregion

    public void SomeGeneratedMethod()
    {

        // This section and all other non-custom code
        // regions will be overwritten during each
        // template execution.
        // Current Date: Saturday, 12 January 2013
    }

#region "Custom Region 2"

    // The contents of this region will also be preserved
    // during generation.

#endregion

}

The template is defined as follows:

<%@ Template Language="C#" TargetLanguage="C#"    Description="Demonstrates using a PreserveRegions merge strategy in C#." %>
public class PreserveRegionsSample
{

#region "Custom Region 1"

    // This is a place holder for your custom code.
    // It must exist so that CodeSmith knows where
    // to put the custom code that will be parsed
    // from the target source file.
    // The region name is used to match up the regions
    // and determine where each region of custom code
    // should be inserted into the merge result.

#endregion

    public void SomeGeneratedMethod()
    {

        // This section and all other non-custom code
        // regions will be overwritten during each
        // template execution.
        // Current Date: <%= DateTime.Now.ToLongDateString() %>
    }

#region "Custom Region 2"

    // The contents of this region will also be preserved
    // during generation.

#endregion

}

Two regions are also defined in the template, and then a Merge policy is set for the template, and there may be multiple Regencys that need to be retained when using PreserveRegion, so you can use RegX to define the Region you want to keep:

CodeSmith Merge policy

This example Downloads

InsertClass policies are used to insert auto-generated code into overloaded code, much like InsertRegion, but InsertClass supports more configurations for more flexibility and power.

The configurations it supports are:

Language String, Required Only VB and C are supported #
ClassName String, Required The class name of the code that needs to be inserted.
PreserveClassAttributes Boolean, defaults to False Whether to keep the class's existing Attributes, the default CodeSmith replaces the class's original Attributes
OnlyInsertMatchingClass Boolean, defaults to False Whether to insert only matching class definitions
MergeImports Boolean, defaults to False Whether to merge the Sport statement
NotFoundAction Enum, defaults to None If the specified class does not find the action after, there are several options available for None, InsertAtBottom, and InsertInParent
NotFoundParent String, no default If NotFoundAction is specified as the parent name corresponding to InsertInParent.

For example, use the following configuration:

Language: C# ClassName: “Pet” PreserveClassAttributes: True OnlyInsertMatchingClass: True MergeImports: True

Existing class definitions:

using System;
using System.ComponentModel.DataAnnotations;
namespace Petshop
{
    [ScaffoldTable(true)]
    public class Pet
    {
        public int Age { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }
}

The code that is automatically generated is as follows:

using System;
using System.Text;
namespace Petshop
{
    public class Pet
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string FullName
        {
            get { return String.Format("{0} {1}", FirstName, LastName); }

        }
    }
}

The combined code using InsertClass is as follows:

using System;
using System.ComponentModel.DataAnnotations;
using System.Text;
namespace Petshop
{
    [ScaffoldTable(true)]
    public class Pet
    {
        public string FirstName { get; set; }

        public string LastName { get; set; }

        public string FullName
        {
            get { return String.Format("{0} {1}", FirstName, LastName); }

        }
    }
}