CodeSmith Merge 策略

2018-08-12 21:16 更新

Merge 策略

前面介紹了 CodeSmith 使用的基本用法,通過(guò)代碼模板來(lái)生成代碼,但如果你修改了自動(dòng)生成的代碼,再次使用代碼模板生成代碼后,你修改的代碼也就丟失了,CodeSmith 支持多種“合并(Merge)”來(lái)解決這個(gè)問(wèn)題,以保留你自己修該過(guò)的部分。

CodeSmith 支持如下三種“合并策略”:

不過(guò)這些策略主要是針對(duì) C#,VB 這些支持 Region 的語(yǔ)言,對(duì)于其它語(yǔ)言可能就需要使用其它方法,比如自定義 Merge 策略,CodeSmith 允許通過(guò) CodeSmith.Engine.IMergeStrategy 來(lái)擴(kuò)展“合并”策略,本人推薦 CodeSmith 的一個(gè)原因就是 CodeSmith 提供了很多接口而不僅僅是一個(gè)工具,比如除了 CodeSmith 支持的屬性,XML 屬性,你也可以通過(guò) CodeSmith.CustomProperties 來(lái)自定義屬性種類,除了 CodeSmith 支持的數(shù)據(jù)源種類(MySQL,Oracle),你也可以通過(guò)自定義的 Schema Provider 支持新的數(shù)據(jù)庫(kù)類型或是其它數(shù)據(jù)類型。

InsertRegion 策略

InsertRegion 顧名思義,就是在源碼中定義一個(gè) Region,然后讓 CodeSmith 自動(dòng)生成的代碼只插入到該區(qū)域,而在區(qū)域外的代碼 CodeSmith 不會(huì)去碰它們,從而實(shí)現(xiàn)了自定義的代碼和自動(dòng)生成代碼的合并。

PreserveRegion 策略

PreserveRegion 是定義多個(gè)區(qū)域,然后通知 CodeSmith 保持這些區(qū)域代碼不變,自動(dòng)創(chuàng)建的代碼添加到這些區(qū)域的外面,和 InsertRegion 作用相反。

下面還是借用 CodeSmith 自帶的 Merge 示例說(shuō)明一下這兩種策略的基本用法:

首先是 InsertRegion 策略,定義一個(gè)類文件 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
}

其中定義了一個(gè) Region,名為 Sample Generated Region ,準(zhǔn)備讓 CodeSmith 查入代碼,編寫(xiě)一個(gè)簡(jiǎn)單的代碼模板,插入當(dāng)前時(shí)間:

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

然后通過(guò) CodeSmith 項(xiàng)目為模板設(shè)置 Merge 策略:

第33張

選擇 InsertRegion 策略, 然后設(shè)置要插入的 RegionName。

生成后的代碼如下:

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
}

可以看到 CodeSmith 只在 Region 處插入代碼,而該 Region 外的部分保持不變。

類似的 PreserveRegions 策略,代碼和模板定義如下: 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

}

模板定義如下:

<%@ 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

}

模板中也定義了兩個(gè)區(qū)域,然后為該模板設(shè)置 Merge 策略,使用 PreserveRegion 時(shí)可能有多個(gè)Region 需要保留,因此可以使用 RegX 來(lái)定義要保留的 Region:

第34張

本例下載

InsertClass 策略用在給以重載的代碼中插入自動(dòng)生成的代碼,挺起來(lái)和 InsertRegion 功能很類似,的確也是如此,但 InsertClass 支持更多的配置,可以實(shí)現(xiàn)更加靈活和強(qiáng)大的功能。

它支持的配置有:

Language String, Required 只支持VB和C#
ClassName String, Required 需插入代碼的類名.
PreserveClassAttributes Boolean, defaults to False 是否保留類已有的Attributes,缺省CodeSmith替代類原來(lái)的Attributes
OnlyInsertMatchingClass Boolean, defaults to False 是否只插入匹配的類定義中
MergeImports Boolean, defaults to False 是否合并Import語(yǔ)句
NotFoundAction Enum, defaults to None 如果指定的類沒(méi)找到后的行動(dòng),可以None,InsertAtBottom,InsertInParent幾種選項(xiàng)
NotFoundParent String, no default 如果指定NotFoundAction為InsertInParent對(duì)應(yīng)的父類名稱.

比如使用如下配置:

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

現(xiàn)有類定義:

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; }
    }
}

自動(dòng)生成的代碼如下:

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); }

        }
    }
}

使用 InsertClass 合并后的代碼如下:

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); }

        }
    }
}
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)