1.如何在模板中添加註釋
CodeSmith:
<%-- Comments --%>
VB.NET:
<%-- 'Comments --%>
C#:
<%-- // Comments --%>
<%-- /* Comments */ --%>
2.創建一個可以下拉選擇的屬性
首先定義一個枚舉類型的變量,然後將屬性的類型設置爲枚舉型
CS_Identity_Example.cst文件源代碼
2
3 <script runat="tempate">
4 public enum CollectionTypeEnum
5 {
6 Vector,
7 HashTable,
8 SortedList
9 }
10 </script>
3.解決ASP.NET中標籤<%重複問題
先將ASP.NET中使用的這個重複標籤寫成<%%,避免在生成代碼時由於是標籤重複引起的編譯錯誤或生成錯誤。
4.如何聲明一個常量
private const string MY_CONST = "example";
</script>
5.如何對模板進行調試
如果要調試一個模板,首先要在代碼模板裏進行聲明,然後在你想要進行調試的地方用Debugger.Break()語句設置斷點即可。
<% Debugger.Break(); %>
6.如何將屬性設置成選擇一個文件夾的路徑
public string OutputDirectory
{
get {return _outputDirectory;}
set {_outputDirectory= value;}
}
7.怎樣調用子模板
2foreach (TableSchema table in SourceDatabase.Tables)
3{
4 OutputSubTemplate(table);
5}
6%>
7<script runat="template">
8private CodeTemplate _mySubTemplate;
9
10[Browsable(false)]
11public CodeTemplate MySubTemplate
12{
13 get
14 {
15 if (_mySubTemplate == null)
16 {
17 CodeTemplateCompiler compiler = new CodeTemplateCompiler(this.CodeTemplateInfo.DirectoryName + "MySubTemplate.cst");
18 compiler.Compile();
19 if (compiler.Errors.Count == 0)
20 {
21 _mySubTemplate = compiler.CreateInstance();
22 }
23 else
24 {
25 for (int i = 0; i < compiler.Errors.Count; i++)
26 {
27 Response.WriteLine(compiler.Errors[ i].ToString());
28 }
29 }
30 }
31 return _mySubTemplate;
32 }
33}
34
35public void OutputSubTemplate(TableSchema table)
36{
37 MySubTemplate.SetProperty("SourceTable", table);
38 MySubTemplate.SetProperty("IncludeDrop", false);
39 MySubTemplate.SetProperty("InsertPrefix", "Insert");
40 MySubTemplate.Render(Response);
41}
42</script>
FAQ中給出的例子爲生成一個數據庫中所有表的更新Update存儲過程
SubTemplatesExample.cst文件源代碼
2 Description="Generates a update stored procedure." %>
3
4<%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema"
5 Category="Context"
6 Description="Database" %>
7
8<%@ Assembly Name="SchemaExplorer" %>
9
10<%@ Import Namespace="SchemaExplorer" %>
11
12<%
13foreach (TableSchema table in SourceDatabase.Tables)
14{
15 OutputSubTemplate(table);
16}
17%>
18
19<script runat="template">
20private CodeTemplate _mySubTemplate;
21
22
23
24
25[Browsable(false)]
26public CodeTemplate MySubTemplate
27{
28 get
29 {
30 if (_mySubTemplate == null)
31 {
32 CodeTemplateCompiler compiler = new CodeTemplateCompiler(this.CodeTemplateInfo.DirectoryName + "MySubTemplate.cst");
33 compiler.Compile();
34
35 if (compiler.Errors.Count == 0)
36 {
37 _mySubTemplate = compiler.CreateInstance();
38 }
39 else
40 {
41 for (int i = 0; i < compiler.Errors.Count; i++)
42 {
43 Response.WriteLine(compiler.Errors[ i].ToString());
44 }
45 }
46 }
47
48 return _mySubTemplate;
49 }
50}
51
52public void OutputSubTemplate(TableSchema table)
53{
54 MySubTemplate.SetProperty("SourceTable", table);
55 MySubTemplate.SetProperty("IncludeDrop", false);
56 MySubTemplate.SetProperty("InsertPrefix", "Insert");
57
58 MySubTemplate.Render(Response);
59}
60</script>
MySubTemplate.cst文件源代碼
2 Description="Generates a update stored procedure." %>
3
4<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
5 Category="Context"
6 Description="Table that the stored procedures should be based on." %>
7
8<%@ Assembly Name="SchemaExplorer" %>
9
10<%@ Import Namespace="SchemaExplorer" %>
11
12
13<script runat="template">
14public string GetSqlParameterStatement(ColumnSchema column)
15{
16 string param = "@" + column.Name + " " + column.NativeType;
17
18 switch (column.DataType)
19 {
20 case DbType.Decimal:
21 {
22 param += "(" + column.Precision + ", " + column.Scale + ")";
23 break;
24 }
25 default:
26 {
27 if (column.Size > 0)
28 {
29 param += "(" + column.Size + ")";
30 }
31 break;
32 }
33 }
34
35 return param;
36}
37</script>
38
39-----------------------------------------------------------------
40-- Date Created: <%= DateTime.Now.ToLongDateString() %>
41-- Created By: Generated by CodeSmith
42-----------------------------------------------------------------
43
44CREATE PROCEDURE dbo.Update<%= SourceTable.Name %>
45 <% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
46 <%= GetSqlParameterStatement(SourceTable.Columns[i]) %><% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>
47 <% } %>
48AS
49
50UPDATE [<%= SourceTable.Name %>] SET
51 <% for (int i = 0; i < SourceTable.NonPrimaryKeyColumns.Count; i++) { %>
52 [<%= SourceTable.NonPrimaryKeyColumns[i].Name %>] = @<%= SourceTable.NonPrimaryKeyColumns[i].Name %><% if (i < SourceTable.NonPrimaryKeyColumns.Count - 1) { %>,<% } %>
53 <% } %>
54WHERE
55 <% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
56 <% if (i > 0) { %>AND <% } %>
57 [<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>] = @<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>
58 <% } %>
8.在加載模板時默認加載的命名空間Namespaces和組件Assemblies
組件:mscorlib, System, System.Xml, System.Data, System.Drawing, Microsoft.VisualBasic, System.Windows.Forms, CodeSmith.Engine
命名空間:System, System.Data, System.Diagnostics, System.ComponentModel, Microsoft.VisualBasic, CodeSmith.Engine
9.使用SchemaExplorer能否確定一個字段(Field)是標識字段(主鍵,Identity Field)
在字段的擴展屬性集合中包含一個叫“CS_IsIdentity”的屬性,如果這個屬性的值爲true,則表名當前字段爲一個標識字段
2 if( ((bool)cs.ExtendedProperties["CS_IsIdentity"].Value) == true)
3 {
4 Response.Write(cs.Name);
5 }
6 }
7 %>
2 Description="Identifies the identity field of a table" %>
3
4 <%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
5 Category="Context"
6 Description="Table to target." %>
7
8 <%@ Assembly Name="SchemaExplorer" %>
9
10 <%@ Import Namespace="SchemaExplorer" %>
11
12
13
14 Identity Field = <% foreach(ColumnSchema cs in SourceTable.Columns) {
15 if( ((bool)cs.ExtendedProperties["CS_IsIdentity"].Value) == true)
16 {
17 Response.Write(cs.Name);
18 }
19 }
20 %>
10.如何確定一個字段的默認值(各人認爲翻譯成如何知道一個字段有默認值並且默認值是什麼)
在字段的擴展屬性集合中包含一個叫“CS_Default”的屬性
2 foreach(ColumnSchema cs in SourceTable.Columns) {
3 if (cs.ExtendedProperties["CS_Default"] != null)
4 {
5 Response.WriteLine(cs.ExtendedProperties["CS_Default"].Value);
6 }
7 }
8 %>
11.如何使用SchemaExplorer得到存儲過程的輸入輸出參數
使用CodeSmith提供的CommandSchema對象,它包含需要的輸入輸出參數集合
2 <%foreach(ParameterSchema ps in SourceProcedure.AllInputParameters)
3 {
4 Response.Write(ps.Name);
5 Response.Write("/n");
6 }
7 %>
8
9
10 Output Parameters:
11 <%foreach(ParameterSchema ps in SourceProcedure.AllOutputParameters)
12 {
13 Response.Write(ps.Name);
14 Response.Write("/n");
15 }
16 %>
InputOutputParameterExample.cst文件源代碼
2 Description="Generates a update stored procedure." %>
3
4 <%@ Property Name="SourceProcedure" Type="SchemaExplorer.CommandSchema"
5 Category="Context"
6 Description="The stored procedure to examine" %>
7
8 <%@ Assembly Name="SchemaExplorer" %>
9
10 <%@ Import Namespace="SchemaExplorer" %>
11
12 Input Parameters:
13 <%foreach(ParameterSchema ps in SourceProcedure.AllInputParameters)
14 {
15 Response.Write(ps.Name);
16 Response.Write("/n");
17 }
18 %>
19
20
21 Output Parameters:
22 <%foreach(ParameterSchema ps in SourceProcedure.AllOutputParameters)
23 {
24 Response.Write(ps.Name);
25 Response.Write("/n");
26 }
27 %>
四、語法與標籤
一下內容介紹在CodeSmith中使用的語法和標籤的參考。
CodeSmith模板語法參考
本文的目的是在編寫一個CodeSmith模板時遇到的各種類型的變量和對象提供參考。本文的目的不是要介紹CodeSmith,如果您想快速瞭解CodeSmith請查看我翻譯的CodeSmith基礎(一)和CodeSmith基礎(二)。
標籤
標籤一般出現在模板的頭部,被用做設置許多不同的屬性。
代碼模板的聲明(CodeTemplate Directive)
這個是模板中唯一必須的聲明,包含一些模板特殊的屬性,包含模板使用的語言、生成的語言和一些對於模板的描述。
例:
參數的介紹:
Language:在開發編寫模板時使用的語言,例如C#,VB.NET,Jscript等。
TargetLanguage:只是對模板代碼的一個分類,不會影響生成的代碼語言。是模板的一個屬性,說明模板要基於那種語言生成相應的代碼。例如你可以用CodeSmith從任何一種語言生成C#代碼。
Description:對於模板的一些說明信息,在CodeSmith Explorer中選中該模板時會顯示這裏的信息。
Inherits:所有CodeSmith模板默認繼承自CodeSmith.Engine.CodeTemplate,這個類提供模板使用的一些基本功能,像ASP.NET頁面的Page類,這些被繼承的類的屬性可以被修改,但是這些新的類也必須繼承CodeSmith.Engine.CodeTemplate。CodeSmith也同樣可以找到這個類,當然你要引入一個組件包含這個類。
Src:在某些方面Src和繼承Inherits比較相似,它們都允許你從其他的類包含一些功能進模板。這兩個屬性的區別是,Src可以讓類與你的模板被動態編譯,而Inherits僅允許你提供一個已經編譯好的類或組件。
Debug:可以確定是否在模板中可以包含調試符號。如果將這個屬性設置爲True,則可以使用System.Diagnostics.Debugger.Break()方法來設置斷點。
LinePragmas:設置爲True,模板的錯誤將被指向到模板的源代碼。設置爲False,模板的錯誤將被指向到編譯的源代碼。
屬性的聲明(Property Directive)
屬性被用做在模板運行時聲明一個使用的參數,例:
屬性參數的介紹:
Name:模版使用的參數的名稱。
Type:參數類型可以是任何.NET有效的數據類型,例如簡單的String類型或者是CodeSmith的SchemaExplorer.DatabaseSchema類型。注意,類型必須是基類庫的類型,例如用String或者Int32代替string和int。
Default:設置默認值。
Category:用來說明這個屬性在CodeSmith Explorer的屬性面板中顯示成什麼類型,例如下拉選擇、直接輸入等。
Description:在屬性面板中對於這個屬性的描述。
Optional:設置這個屬性是否是必須的,設置爲True表明這個參數值可有可無,設置爲False則這個參數必須有值。
Editor:表明在屬性面板中輸入這個屬性的值時使用何種GUI(圖形界面編輯器)編輯器。
EditorBase:編輯器使用的基本類型,如果沒有被說明,UITypeEditor爲默認編輯器。
Serializer:這塊我的水平不太會犯疑:)The serializer parameter specifies the IPropertySerializer type to use when serializing the properties values. This is equivalent to using a [PropertySerializerAttribute].
XML屬性聲明(XmlProperty Directive)
例:屬性的參數:
Name:名稱。
Schema:這個參數用來指定一個XSD文件,創建一個強類型對象模型。如果這個計劃被指定,編譯器會嘗試分析這個XSD文件併爲這個計劃生成一個強類型對象模型,這樣可以在模版中使用強類型和智能與XML協同工作。如果這個計劃沒有被設定,這個參數將爲XmlDocument類型並且將使用XML DOM去導航到一個XML內容並生成代碼。
Category:在CodeSmith屬性面板中的類別。
Description:描述。
Optional:這個參數是否是必須的,如果設置爲True,則參數不是必須的,反之False則爲必須的。在設置爲False時,如果用戶沒有提供參數則CodeSmith不能繼續運行。
註冊的聲明(Register Directive)
這個屬性通常被用作引入另一個模版文件並與當前的模版文件同時被編譯。這是一種使用子模版的交互方法。
例:
XML
模版一旦被註冊,就可以建立一個模版的實例,然後象這樣設置它的屬性:
2 public void OutputSubTemplate()
3 {
4 MySubTemplate mySubTemplate = new MySubTemplate();
5
6 // set an individual properties value.
7 mySubTemplate.SomeExcludedPropertyName = "SomeValue";
8
9 // copy all properties with matching name and type to the sub template instance.
10 this.CopyPropertiesTo(mySubTemplate);
11
12 // render the template to the current templates Response object.
13 mySubTemplate.Render(this.Response);
14
15 // render the template to a file.
16 mySubTemplate.RenderToFile("C:/SomeFile.txt");
17 }
18 </script>
註冊的參數:
Name:代表被引入的模版的名稱。它可以被用作創建一個模版的實例。
Template:被引入模版文件的相對路徑,它可以與當前的模版一起被動態的編譯。
MergeProperties:設置成True時,所有被引用的面板的屬性將被動態的添加到當前模版中。
ExcludePorperties:當使用MergeProperties時,你可能不需要某些屬性被添加到當前模版中。將不需要的屬性以逗號分隔放在這裏,*號可以被用作通配符使用。
組件的聲明(Assembly Directive)
用作在模版中引用一個外部部組件,或者包含一個編譯好的源文件。
例:或
CodeSmith自動加載一些不同的組件:System, System.Diagnostics, System.ComponentModel, Microsoft.VisualBasic, CodeSmith.Engine
組件的參數:
Name:需要引用組件的名稱,組建必須存在於Global Assembly Cache,與CodeSmith在同一路徑下或與模版文件在同一路徑下。
Src:要包含文件的相對路徑。
引入的聲明(Import Directive)
在模版中引入一個命名空間,這個與VB.NET中的Imports和C#中的using相同。
例:引入的參數:
NameSpace:被引入的命名空間的名字。記住同時必須要加載包含這個命名空間的相應組件,除非這個組件是被默認加載的。