前面介紹了 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 顧名思義,就是在源碼中定義一個(gè) Region,然后讓 CodeSmith 自動(dòng)生成的代碼只插入到該區(qū)域,而在區(qū)域外的代碼 CodeSmith 不會(huì)去碰它們,從而實(shí)現(xiàn)了自定義的代碼和自動(dòng)生成代碼的合并。
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 策略:
選擇 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:
本例下載
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); }
}
}
}
更多建議: