CodeSmith快速嚮導

來源:互聯網
上載者:User

本文檔的目的就是讓你儘快得知道怎麼通過CodeSimth從一個集合中產生你需要的完整程式。
在本嚮導裡,我打算教你使用CodeSmith內建的模版,如何建立一個模版以及如何建立一個資料
庫驅動模版。
 
CodeSimth是一個基於模版基礎的代碼產生工具,通過使用一個類似Asp.net的文法你可以建立和
定義一個用於產生代碼的模版。你應該知道的一個重要的事情是:CodeSimth產生的代碼是文本的,
因此你可以用它產生那些你沒有必要編寫的其他語言的代碼或者文本。
 
在看如何建立你自己的模版之前,讓我們先用下CodeSmith內建的模版.你可以通過:開始->程式->
CodeSmith->CodeSmith Explorer 來啟動CodeSmith Explorer.啟動後的介面如所示:
 
CodeSmith Explorer用來現實你可以使用的模版;預設的樣本模版是被載入的。許多常用的模版在集合頂部,
雙擊ArArrayList.cst模版開啟,將看到如所示:
 
這是一個模版屬性面板,你可以查看和指定多個模版的屬性。對於ArrayList模版我們需要指定我們想建立的
ArrayList的名稱和我們想儲存在ArrayList內item的類型。(我們也可以隨意指定一個命名空間以使用ArrayList)本
例子裡我們指定CarList作為ClassName,Car作為ItemType.添好屬性之後單擊Generate,模版將為你產生一個強型別
的ArrayList。
(譯者註:我的CodeSmith v 2.6 professional 版點了Generate後沒反應,你可以到CodeSmith Studio 裡面試)
 
右面的視窗顯示了使用為Car類產生一個強型別ArrayList模版後的輸出結果,
接著你可以把他拷貝和複製到Visual Studio總,或者其他你用的編輯器中編譯它。
 
(譯者註:我的CodeSmith v 2.6 professional 版 點了Generate後沒反應,你可以到CodeSmith Studio
裡面試。開始-〉程式->CodeSimith v2.6->CodeSmith Studio,
右邊面板,展開Collections->雙擊ArrayList.cst,填入
下面Properties面版裡面的ClassName和ItemType值.->
點工具列裡的運行(小三角形))
 
編寫你的第一個模版
CodeSmith和其他的代碼產生工具相比較,最有價值的是:
你可以通過編寫你需要產生的程式碼的代碼產生模版,你可以
規定它代碼如何產生,甚至指定在代碼裡面tabs和空格的
數量。你可以完全控制你的代碼輸出,其他的工具幾乎不可能完成
這樣的功能。
 
你用來產生模版的工具已經有一堆不同的功能,如果你正在使用個人版的
CodeSmith,你可以使用CodeSmith Studio,它有豐富的CodeSmith
模版環境。如果你沒有使用個人版或者試用到期,那麼你可以使用任何的文本編輯
器建立你的模版。
 
下面我們將建立一個簡單的模版,它接受一些字串然後建立一個包含了特殊注釋頭的
類。這是一個簡單的例子,但它將展示CodeSmith模版建立的基礎。我發現設計一個模
版最好的方式是首先建立一個模版的需要輸出結果的代碼,下面個就是模版將輸出的內
容:

///////////////////////////////////////////////////////////////////////////////////////
// File: MyClass.cs
// Description: Enter summary here after generation.
// ---------------------
// Copyright ? 2003 Our Client
// ---------------------
// History
//    11/30/2003    Developer''''s Name    Original Version
///////////////////////////////////////////////////////////////////////////////////////
 
using System;
 
namespace MyNamespace
{
      /// <summary>
      /// Summary description for MyClass.
      /// </summary>
      public class MyClass
      {
            public MyClass()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }
      }
}

這就是我們想模版最終產生的結果,不過我們需要在模版每次運行時指定一些東西。
那麼現在讓我們來開始編寫模版吧。
 
首先開啟一個空白的文字檔,並在檔案頭部增加一個CodeTemplate的標籤。
CodeTemplate 標籤告訴CodeSmith這是一個模版檔案,和模版用什麼語言編寫的,
模版產生的語言以及模版描述。下面是一個CodeTemplate標籤:
<%@ CodeTemplate Language="C#" TargetLanguage="C#"
      Description="Generates a class including a special informational header" %>
 
首先我們設定模版語言為C#,接著設定模版產生的語言為C#,然後添加模版描述。
還有一些其它的屬性可以在標籤中增加,它將在文檔其他的地方被代替。
 
接著聲明模版在運行時候需要的變數。本例模版中想指定命名空間的名稱,類名和
開發人員的名稱。下面是三個需要聲明的屬性:
 
<%@ Property Name="NameSpace" Type="String"
      Category="Context"
      Description="The namespace to use for this class" %>
 
<%@ Property Name="ClassName" Type="String"
      Category="Context"
      Description="The name of the class to generate" %>
 
<%@ Property Name="DevelopersName" Type="String"
      Category="Context"
      Description="The name to include in the comment header" %>
 
每個屬性標籤包括Name屬性,它被用來做模版其它地方的屬性的值和屬性類型的參考。
我們已經為每個屬性設定了一個類別和描述,這些在模版被CodeSmith開啟的時候可以
用來定義相關的屬性。
 
接著修改模版文本以便當屬性被指定時候文本文字可以被插入到正確位置。
你可以使用Asp.Net類似的文法和屬性名稱來操作,比如:
///////////////////////////////////////////////////////////////////////////////////////
// File: <%=ClassName%>.cs
 
值將被文本替代,正如你說見文法和Asp.net類似。我們想看到我們所希望的剩餘部分
和用屬性名稱替換硬式編碼。這個執行個體模版全部內容:
<%@ CodeTemplate Language="C#" TargetLanguage="C#"
      Description="Generates a class including a special informational header" %>
 
<%@ Property Name="NameSpace" Type="String"
      Category="Context"
      Description="The namespace to use for this class" %>
 
<%@ Property Name="ClassName" Type="String"
      Category="Context"
      Description="The name of the class to generate" %>
 
<%@ Property Name="DevelopersName" Type="String"
      Category="Context"
      Description="The name to include in the comment header" %>
     
///////////////////////////////////////////////////////////////////////////////////////
// File: <%=ClassName%>.cs
// Description: Enter summary here after generation.
// ---------------------
// Copyright ? <%= DateTime.Now.Year %> Our Client
// ---------------------
// History
//    <%= DateTime.Now.ToShortDateString() %>    <%= DevelopersName%>    Original Version
///////////////////////////////////////////////////////////////////////////////////////
 
using System;
 
namespace <%=NameSpace %>
{
      /// <summary>
      /// Summary description for <%=ClassName %>.
      /// </summary>
      public class <%=ClassName %>
      {
            public <%=ClassName %>()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }
      }
}

正如你所看到的我們在幾個不同的地方應用了我們定義的那些屬性,我們也使用了
DateTime對象去為我們顯示一個時間。現在我們需要在CodeSmith explorer中調用
這個模板,運行你的CodeSmith explorer,單擊檔案夾表徵圖選擇模板檔案所在的目錄
。你會看到目錄下的所有模板列表,接著雙擊模板載入他。模板載入之後我們可以
在面板上看到他的屬性列表,

可以看到我們聲明的三個屬性,包括類別說明和描述。當你單擊產生按鈕後,CodeSmith使用指
定的屬性和我們的模板代碼產生下列的內容。

///////////////////////////////////////////////////////////////////////////////////////
// File: MyClass.cs
// Description: Enter summary here after generation.
// ---------------------
// Copyright ? 2003 Our Client
// ---------------------
// History
//    12/2/2003    Mr. Smith    Original Version
///////////////////////////////////////////////////////////////////////////////////////
 
using System;
 
namespace MyNameSpace
{
      /// <summary>
      /// Summary description for MyClass.
      /// </summary>
      public class MyClass
      {
            public MyClass()
            {
                  //
                  // TODO: Add constructor logic here
                  //
            }
      }
}

你可以把產生的程式碼拷粘貼到Visual Studio或其他你使用的編譯器中,然後
編譯他們。

這是一個CodeSmith可以做什麼的最簡單的例子,但列舉了一些要點:
。模板應該包括一個CodeTemplate聲明;
。模板可以有很多個屬性和用屬性聲明的被聲明的屬性。
。使用asp.net文法把屬性值插入到輸出的模板中
。模板是100%定製的,你可以用CodeSmith產生任何種類的文本。

可是上面的例子還不能真正的展示CodeSmith的強大能力,下節中
我們會看到怎麼樣基於資料庫物件動態產生代碼。

編寫一個資料庫驅動的模板

現在我們已經認識了哪些怎麼樣使用CodeSmith配合我們工作的要素,
我們接著學如何產生你可能下載CodeSmith首先想要產生的東西。
資料訪問邏輯可能是程式中最多餘的部分,使用CodeSmith你可
以自動產生相當正規的資料訪問層代碼。最後章節你可以看到如何
編寫一個簡單的支援參數的模板,但是現在我們打算看看如何
通過使用CodeSmith的SchemaExplorer組件編寫模板。SchemaExplorer
組件是一個程式集,它提供了多個可以用來瀏覽你資料庫內容的類。
通過使用SchemaExplorer組件你可以瀏覽表和預存程序以及取到資料
類型,唯一列,列名等資訊。

作為一個如何使用SchemaExplorer的例子,我們打算編寫一個根據
表列自動產生預存程序的模板。開始編寫模板前我們應該編寫一個
希望模板產生的常值內容,這樣我們可以使用這些文本作為模板的
開始。下面是我們期望產生的文本:
-----------------------------------------------------------------
-- Date Created: Thursday, December 04, 2003
-- Created By:   Generated by CodeSmith
-----------------------------------------------------------------
 
CREATE PROCEDURE dbo.UpdateOrders
      @OrderID int,
      @CustomerID nchar(5),
      @EmployeeID int,
      @OrderDate datetime,
      @RequiredDate datetime,
      @ShippedDate datetime,
      @ShipVia int,
      @Freight money,
      @ShipName nvarchar(40),
      @ShipAddress nvarchar(60),
      @ShipCity nvarchar(15),
      @ShipRegion nvarchar(15),
      @ShipPostalCode nvarchar(10),
      @ShipCountry nvarchar(15)
AS
 
UPDATE [Orders] SET
      [CustomerID] = @CustomerID,
      [EmployeeID] = @EmployeeID,
      [OrderDate] = @OrderDate,
      [RequiredDate] = @RequiredDate,
      [ShippedDate] = @ShippedDate,
      [ShipVia] = @ShipVia,
      [Freight] = @Freight,
      [ShipName] = @ShipName,
      [ShipAddress] = @ShipAddress,
      [ShipCity] = @ShipCity,
      [ShipRegion] = @ShipRegion,
      [ShipPostalCode] = @ShipPostalCode,
      [ShipCountry] = @ShipCountry
WHERE
      
      [OrderID] = @OrderID
 

這是一個更新Northwind資料庫Orders表的預存程序,因為是一個
十分普通的預存程序,所以是一個很好的代碼產生模型。模板的目
標是從表裡讀取資訊然後自動產生對應的預存程序,當然可以適用
其他表不僅僅是本表。

首先在模板裡建立CodeTemplate標籤描述模板名字和說明。
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL"
      Description="Generates a update stored procedure." %>
接著我們需要調用包含了SchemaExplorer的程式集,此類有利
於我們通過程式集標籤訪問資料庫。

<%@ Assembly Name="SchemaExplorer" %>

我們需要使用import標籤匯入SchemaExplorer的命名空間,載入SchemaExplorer
程式集,以便我們可以在模板裡訪問它的類,
<%@ Import Namespace="SchemaExplorer" %>

因為我們打算從表裡讀資料,我們需要在模板裡增加
一個TableSchema類型的屬性。
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
      Category="Context"
      Description="Table that the stored procedures should be based on." %>

當我們執行模板時,這個屬性允許我們選擇一個資料庫和表格。我們可以參考這個屬性
去檢測表和建立基於表的內容和屬性的我們的模板。

接著開始些輸出文本的模板節點。第一個節點是如下可見的檔案頭。
-----------------------------------------------------------------
-- Date Created: <%= DateTime.Now.ToLongDateString() %>
-- Created By:   Generated by CodeSmith
-----------------------------------------------------------------
代碼和最後例子裡的類似,我們使用DateTime對象為我們的檔案生
成時間。然後我們需要建立預存程序指令碼的首行:
CREATE PROCEDURE dbo.Update<%= SourceTable.Name %>
在本行裡我們使用早先定義的 SourceTable的Name屬性,它將插入
我們在測試的表名,因此本例中因為我們對應的是Orders表所以
預存程序將是UPdateOrders.

接下來我們為預存程序建立參數列表,因為我們要建立一個更新的儲存
過程我們需要表的每個列名做參數。使用TableSchema 對象我們可以循
環表中的列讀出列名和列的資料類型,使用值去建立我們的列表。
      <% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
      <%= GetSqlParameterStatement(SourceTable.Columns[i]) %>
      <% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>
      <% } %>
AS

我們需要建立一個帶參數的更新表的SQL語句。因此我需要再迴圈
列集合,但是應該用NonPrimaryKeyColumns 集合替換normal
columns 進行。我們這樣做是因為我們僅想更行非主建列。我們
將在更新語句的where條件中用主鍵列。
UPDATE [<%= SourceTable.Name %>] SET
      <% for (int i = 0; i < SourceTable.NonPrimaryKeyColumns.Count; i++) { %>
      [<%= SourceTable.NonPrimaryKeyColumns[i].Name %>] = @<%= SourceTable.NonPrimaryKeyColumns[i].Name %><% if (i < SourceTable.NonPrimaryKeyColumns.Count - 1) { %>,<% } %>
      <% } %>

下列的語句中我們要建立SET列表,列表包含了列名和參數名,下面是
CodeSmith執行後產生的文本:
UPDATE [Orders] SET
      [CustomerID] = @CustomerID,
      [EmployeeID] = @EmployeeID,
      [OrderDate] = @OrderDate,
      [RequiredDate] = @RequiredDate,
      [ShippedDate] = @ShippedDate,
      [ShipVia] = @ShipVia,
      [Freight] = @Freight,
      [ShipName] = @ShipName,
      [ShipAddress] = @ShipAddress,
      [ShipCity] = @ShipCity,
      [ShipRegion] = @ShipRegion,
      [ShipPostalCode] = @ShipPostalCode,
      [ShipCountry] = @ShipCountry

模板的最後部分我們需要編寫update語句的where字句。
再次的使用列迴圈,但是這次我們從表的主見列中迴圈
來產生where字句。

WHERE
      <% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
      <% if (i > 0) { %>AND <% } %>
      [<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>] = @
      <%= SourceTable.PrimaryKey.MemberColumns[i].Name %>
      <% } %>

下面是CodeSmith產生的文本:
WHERE
      
      [OrderID] = @OrderID

下面是完整的模板:
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL"
      Description="Generates a update stored procedure." %>
 
<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema"
      Category="Context"
      Description="Table that the stored procedures should be based on." %>
 
<%@ Assembly Name="SchemaExplorer" %>
 
<%@ Import Namespace="SchemaExplorer" %>
      
<script runat="template">
public string GetSqlParameterStatement(ColumnSchema column)
{
      string param = "@" + column.Name + " " + column.NativeType;
 
      switch (column.DataType)
      {
            case DbType.Decimal:
            {
                  param += "(" + column.Precision + ", " + column.Scale + ")";
                  break;
            }
            default:
            {
                  if (column.Size > 0)
                  {
                        param += "(" + column.Size + ")";
                  }
                  break;
            }
      }
 
      return param;
}
</script>
 
-----------------------------------------------------------------
-- Date Created: <%= DateTime.Now.ToLongDateString() %>
-- Created By:   Generated by CodeSmith
-----------------------------------------------------------------
 
CREATE PROCEDURE dbo.Update<%= SourceTable.Name %>
      <% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
      <%= GetSqlParameterStatement(SourceTable.Columns[i]) %><% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>
      <% } %>
AS
 
UPDATE [<%= SourceTable.Name %>] SET
      <% for (int i = 0; i < SourceTable.NonPrimaryKeyColumns.Count; i++) { %>
      [<%= SourceTable.NonPrimaryKeyColumns[i].Name %>] = @<%= SourceTable.NonPrimaryKeyColumns[i].Name %><% if (i < SourceTable.NonPrimaryKeyColumns.Count - 1) { %>,<% } %>
      <% } %>
WHERE
      <% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
      <% if (i > 0) { %>AND <% } %>
      [<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>] = @<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>
      <% } %>

當我們在CodeSmith中載入模板的時候可以看見 SourceTable 屬性
,屬性在右邊包含了一個按鈕,你可以通過選擇一個表來運行儲存
過程產生的模板。下面是界圖:

 點右邊的按鈕去選擇一個表,你可以看見如:
 在界圖中你可以配置你的資料來源(通過選擇展開按鈕選擇另一
 個資料庫)。接著選你想要模板產生代碼的表。選擇表點產生
 後下面的文本將被產生:
 -----------------------------------------------------------------
-- Date Created: Saturday, December 06, 2003
-- Created By:   Generated by CodeSmith
-----------------------------------------------------------------
 
CREATE PROCEDURE dbo.UpdateOrders
      @OrderID int,
      @CustomerID nchar(5),
      @EmployeeID int,
      @OrderDate datetime,
      @RequiredDate datetime,
      @ShippedDate datetime,
      @ShipVia int,
      @Freight money,
      @ShipName nvarchar(40),
      @ShipAddress nvarchar(60),
      @ShipCity nvarchar(15),
      @ShipRegion nvarchar(15),
      @ShipPostalCode nvarchar(10),
      @ShipCountry nvarchar(15)
AS
 
UPDATE [Orders] SET
      [CustomerID] = @CustomerID,
      [EmployeeID] = @EmployeeID,
      [OrderDate] = @OrderDate,
      [RequiredDate] = @RequiredDate,
      [ShippedDate] = @ShippedDate,
      [ShipVia] = @ShipVia,
      [Freight] = @Freight,
      [ShipName] = @ShipName,
      [ShipAddress] = @ShipAddress,
      [ShipCity] = @ShipCity,
      [ShipRegion] = @ShipRegion,
      [ShipPostalCode] = @ShipPostalCode,
      [ShipCountry] = @ShipCountry
WHERE
     
      [OrderID] = @OrderID

本模板可以產生任意資料庫任意表的更新預存程序。
結論
真心的希望這個快速協助可以為你使用CodeSmith提供
足夠的資訊和例子.CodeSmith是一個十分有力和省時的工具,
希望你可以在你的工程中發現更多的用處就像我們一樣。

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.