codeSmith 使用实例

来源:互联网 发布:八皇后问题 python 编辑:程序博客网 时间:2024/06/10 23:27

  使用FileDialogAttribute可以设置FileNameEditor中的属性,基本成员如下:

属性

描述

默认值

FileDialogType

Save or Open

FileDialogType.Save

Filter

Filter string for file extensions

All Files (*.*)|*.*

Title

Dialog box title

Select propertyname

DefaultExtension

Default file extensions

None

CheckFileExists

True to only allow selecting existing files

False

CheckPathExists

True to only allow using existing paths

False

在下面这段模版代码中,我们设置了弹出的对话框的类型为打开文件对话框,标题为“Select Input File”。

 1private string _openFileName = @"c:/temp/test.txt";
 2[Editor(typeof(FileNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 3FileDialogAttribute(FileDialogType.Open, Title="Select Input File"),
 4Category("Custom"), Description("User selected file.")]
 5public string OpenFileName
 6{
 7      get {return _openFileName;}
 8      set {_openFileName= value;}
 9}

10
11执行
12

 

 

 

SchemaExplorer允许我们获取数据库中一些对象的信息。如果你使用的是SQL Server2000数据库,你可以通过扩展属性获取很多对象的有用的信息。例如:SQL Server定义了一个扩展属性来标识表中的唯一标识字段,在模版中可以这样写: CodeSmith定义的扩展属性包括table columns, view columns, command parameters

Identity Field = <% foreach(ColumnSchema cs in SourceTable.Columns) 
      
if( ((bool)cs.ExtendedProperties["CS_IsIdentity"].Value) == true)
      
{
            Response.Write(cs.Name);
      }

}

%>

 

 

Table columns

 

 CS_IsRowGuidCol

 CS_IsIdentity

 CS_IsComputed

 CS_IsDeterministic

 CS_IdentitySeed

 CS_IdentityIncrement

 CS_Default

view columns

 CS_IsComputed

 CS_IsDeterministic

 command parameters

 CS_Default

另外,每个对象都有一个CS_Description的扩展属性。你也可以通过SQL Server中的系统存储过程sp_addextendedproperty来创建自定义的扩展属性。例如:我们执行如下命令为Customer这张表的ID字段添加一个Caption的扩展属性:

sp_addextendedproperty 'caption''Customer ID''user', dbo, 'table', Customers, 'column', id

在数据库中执行完这条语句后,CodeSmith中将会在这个字段的扩展属性集合中加上Caption属性。有关SQL Server 中的扩展属性的内容请参考联机丛书。

 

 

CodeSmith生成可变化的代码,其实是先利用CodeSmith生成一个基类,然后自定义其它类继承于该类。当我们重新生成基类时CodeSmith不要接触继承的子类中的代码。看下面的这段模版脚本: 执行该模版并输入如下数据:

<%@ CodeTemplate Language="C#" TargetLanguage="C#" Description="Base class generator." %>
<%@ Property Name="ClassName" Type="System.String" Description="Name of the class." %>
<%@ Property Name="ConstructorParameterName" Type="System.String" Description="Constructor parameter name." %>
<%@ Property Name="ConstructorParameterType" Type="System.String" Description="Data type of the constructor parameter." %>
class <%= ClassName %>
{
    
<%= ConstructorParameterType %> m_<%= ConstructorParameterName %>;
 
    
public <%= ClassName %>(<%= ConstructorParameterType %> <%= ConstructorParameterName %>)
    
{
        m_
<%= ConstructorParameterName %> = <%= ConstructorParameterName %>
    }

}

 

 

该模版生成的代码可能如下:

 

 1class Account
 2{
 3    int m_balance;
 4 
 5    public Account(int balance)
 6    {
 7        m_balance = balance
 8    }

 9
10}

11
12

把生成的文件保存为Account.cs文件。这时我们可以编写第二个类生成Check.cs文件代码:

1class Checking : Account
2{
3    public Checking : base(0)
4    {
5    }

6}

现在如果需要改变Account Balance的类型为浮点型,我们只需要改变ConstructorParameterType属性为float,并重新生成Account.cs文件即可而不需要直接在Account.cs中进行手工修改,并且不需要修改Check.cs文件的任何代码。

 

 

CodeSmith允许我们存储元数据在XML文件中,然后在执行模版时直接打开XML文件填写到属性面板中。

1XML Property With a Schema

 

 1<?xml version="1.0" encoding="UTF-8"?>
 2<xs:schema targetNamespace=http://www.codesmithtools.com/PO
 3     xmlns:xs=http://www.w3.org/2001/XMLSchema
 4     xmlns=http://www.codesmithtools.com/PO
 5     elementFormDefault="qualified" attributeFormDefault="unqualified">
 6   <xs:element name="PurchaseOrder">
 7     <xs:complexType>
 8       <xs:sequence>
 9         <xs:element name="PONumber" type="xs:string"/>
10         <xs:element name="CustomerName" type="xs:string"/>
11         <xs:element name="CustomerCity" type="xs:string"/>
12         <xs:element name="CustomerState" type="xs:string"/>
13         <xs:element name="Items">
14          <xs:complexType>
15            <xs:sequence>
16              <xs:element name="Item" maxOccurs="unbounded">
17                <xs:complexType>
18                  <xs:attribute name="ItemNumber" type="xs:string" use="required"/>
19                  <xs:attribute name="Quantity" type="xs:integer" use="required"/>
20                </xs:complexType>
21              </xs:element>
22            </xs:sequence>
23          </xs:complexType>
24         </xs:element>
25       </xs:sequence>
26     </xs:complexType>
27   </xs:element>
28</xs:schema>
29
30

这是一个简单的带有SchemaXML Property的例子:

利用这个Schema文件,我们可以定义一个XML Property来在运行时读去元数据。

 

<%@ CodeTemplate Language="C#" TargetLanguage="Text" Description="Create packing list from XML PO." %>
<%@ XmlProperty Name="PurchaseOrder" Schema="PO.xsd" Optional="False" Category="Data" Description="Purchase Order to generate packing list for." %>
Packing List
ref: PO#<%= PurchaseOrder.PONumber %>
Ship To:
<%= PurchaseOrder.CustomerName %>
<%= PurchaseOrder.CustomerCity  %><%= PurchaseOrder.CustomerState %>
Contents:
<% for (int i = 0; i < PurchaseOrder.Items.Count; i++%>
<%= PurchaseOrder.Items[i].ItemNumber %>, Quantity <%= PurchaseOrder.Items[i].Quantity %>
<% }
 %>

在运行时,PurchaseOrder属性在属性面板中显示为按钮,单击后弹出一个对话框供用户选择XML文件。

选择一个XML文件。在该例子XML文件内容如下:

 

 1<?xml version="1.0" encoding="UTF-8"?>
 2<PurchaseOrder xmlns=http://www.codesmithtools.com/PO
 3     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
 4   <PONumber>5271</PONumber>
 5   <CustomerName>John Nelson</CustomerName>
 6   <CustomerCity>Gamonetta</CustomerCity>
 7   <CustomerState>MS</CustomerState>
 8   <Items>
 9     <Item ItemNumber="HM85" Quantity="12"/>
10     <Item ItemNumber="JR82" Quantity="4"/>
11     <Item ItemNumber="PR43" Quantity="6"/>
12   </Items>
13</PurchaseOrder>
14
15

生成后的代码如下:

Packing List
ref: PO#5271
Ship To:
John Nelson
Gamonetta, MS
Contents:
HM85, Quantity 12
JR82, Quantity 4
PR43, Quantity 6

2XML Property Without a Schema

这是一个不带SchemaXML Property的例子。这个模版在运行时可以访问任何XML文件。

 

<%@ CodeTemplate Language="VB" TargetLanguage="Text" Description="List top-level nodes in an XML file." %>
<%@ XmlProperty Name="TargetFile" Optional="False" Category="Data" Description="XML file to iterate." %>
<%@ Assembly Name="System.Xml" %>
<%@ Import Namespace="System.Xml" %>
Top
-level nodes:
<% Dim currNode as XmlNode
currNode 
= TargetFile.DocumentElement.FirstChild
Do Until currNode Is Nothing
%>
   
<%= currNode.InnerXml %>
<% currNode = currNode.NextSibling()
Loop 
%>

概莫版对目标文件的属性并没有定义一个Schema,所以属性在模版中是作为一个XMLDocument。如果我们选择的XML文件如下所示:

1<?xml version="1.0" encoding="UTF-8"?>
2<Books>
3   <Book>UML 2.0 In a Nutshell</Book>
4   <Book>The Best Software Writing</Book>
5   <Book>Coder to Developer</Book>
6   <Book>Code Complete</Book>
7</Books>

生成后的代码:

Top-level nodes:
UML 2.0 In a Nutshell
The Best Software Writing
Coder to Developer
Code Complete

 

 

 

 在使用CodeSmith进行代码生成的时候,你可能需要在子模版和父模版之间共享属性。比如,写一个基于数据库生成代码的模版,在每个模版里面都定义了一个名为Server的属性。当你在父模版中使用此属性时,它的值只对父模版起作用。想要设置此值到子模版,可以在父模版中使用CopyPropertiesTo方法,当在父模版中使用此属性时,它的值会发送到子模版中去。下面这段代码展示了如何使用该方法:

  // instantiate the sub-template
   Header header = new Header();
   
// copy all properties with matching name and type to the sub-template instance
   this.CopyPropertiesTo(header);

 

 

CodeSmith中,要把生成的代码文件输出到文件中,你需要在自己的模版中继承OutputFileCodeTemplate类。

<%@ CodeTemplate Language="C#" TargetLanguage="C#" Inherits="OutputFileCodeTemplate" Description="Build custom access code." %>
<%@ Assembly Name="CodeSmith.BaseTemplates" %>

OutputFileCodeTemplate主要做两件事情:

1.它添加一个名为OutputFile的属性到你的模版中,该属性要求你必须选择一个文件;

2.模版重载了方法OnPostRender(),在CodeSmith生成代码完成后把相应的内容写入到指定的文件中去。

如果想要自定义OutputFile属性弹出的保存文件对话框,你需要在你的模版中重载OutputFile属性。例如:你希望用户选择一个.cs文件来保存生成的代码,需要在你的模版中添加如下代码:

<script runat="template">
// Override the OutputFile property and assign our specific settings to it.
[FileDialog(FileDialogType.Save, Title="Select Output File", Filter="C# Files (*.cs)|*.cs", DefaultExtension=".cs")]
public override string OutputFile
{
    
get {return base.OutputFile;}
    
set {base.OutputFile = value;}
}

</script>

 

CodeSmith中,CodeTemplate.Render方法是在模版执行完成进行模版输出时执行,你可以通过重载CodeTemplate.Render方法来修改CodeSmith输出时的事件处理。例如:你可以修改模版输出时的方式来代替现在默认的方式,下面这段代码展示了在保持CodeSmith默认的窗口显示的同时,把结果输出到两个不同的文件。 注意不能忘了base.Render(writer);这句话,否则你将不能获得默认的输出。当重载CodeTemplate.Render方法时,你也可

以访问
TextWriter,也就是说你也可以直接添加其它的附属信息到模版输出的内容中。

 1<%@ CodeTemplate Language="C#" TargetLanguage="Text" Description="AddTextWriter Demonstration." %>
 2<%@ Import Namespace="System.IO" %>
 3This template demonstrates using the AddTextWriter method
 4to output the template results to multiple locations concurrently.
 5<script runat="template">
 6public override void Render(TextWriter writer)
 7{
 8    StreamWriter fileWriter1 = new StreamWriter(@"C:/test1.txt"true);
 9     this.Response.AddTextWriter(fileWriter1);
10 
11    StreamWriter fileWriter2 = new StreamWriter(@"C:/test2.txt"true);
12     this.Response.AddTextWriter(fileWriter2);
13 
14    base.Render(writer);
15 
16    fileWriter1.Close();
17    fileWriter2.Close();
18}

19</script>