CodeSmith实用技巧(转载)

摘自:TerryLes http://terrylee.cnblogs.com/archive/2005/12/26/304865.html

CodeSmith
实用技巧(一):使用StringCollection

  StringCollection提供了一种集合的输入方式,在代码中,可以用Array的方式来引用。在使用这个类之前,在模版中我们必须添加对CodeSmith.CustomProperties程序集的引用:

<%@ Assembly Name="CodeSmith.CustomProperties"%>

添加完程序集之后,我们就可以使用StringCollection在脚本块中定义一个属性:

%@ Property Name="List" Type="CodeSmith.CustomProperties.StringCollection" Category="Custom" Description="This is a sample StringCollection"%>

执行该模版时,这个属性将在属性窗体中显示为一个按钮:

单击按钮,将会弹出一个String Collection Editor对话框:

当然也可以直接在属性窗口中编辑StringCollection

模版代码如下:

 1 <%@ CodeTemplate Language="C#" TargetLanguage="C#" %>
 3 <%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Property Name="List" Type="CodeSmith.CustomProperties.StringCollection" Category="Custom" Description="This is a sample StringCollection" %>
 6
 7 using System;
 8 namespace Test
   {       
11          /**//// <summary>
12          ///     
测试StringCollection
14       /// </summary>
16             public class Test
18 19       {
20                   public static void Main(string[] args)
22                     {
24                            <%for(int i = 0;i<List.Count;i++) {%>
26                             Console.WriteLine(<%=List[i]%>);
28                          <%}%>

31                    }

33          }

35 }
生成后的代码:

 1 using System;

2 namespace Test {       
 6          /**////<summary>
 7          ///     测试StringCollection
           
/// </summary>
2          public class Test
         
{

                public static void Main(string[] args)  {
19                             Console.WriteLine(Apples);
21                             Console.WriteLine(Fish);
23                    }
25          }
27 }

  StringCollection的重要属性和方法:

公共属性

名称

描述

Count

获取StringCollection中包含的字符串的数目

IsReadOnly

获取用于指示StringCollection是否为只读的值

IsSynchronized

获取一个值,该值指示对StringCollection 的访问是否为同步的(线程安全的)

Item

获取或设置指定索引处的元素。在C# 中,该属性为 StringCollection 类的索引器

SyncRoot

获取可用于同步对StringCollection 的访问的对象

公共方法

名称

描述

Add

将字符串添加到 StringCollection 的末尾

AddRange

将字符串数组的元素复制到 StringCollection 的末尾

Clear

移除 StringCollection 中的所有字符串

Contains

确定指定的字符串是否在 StringCollection

CopyTo

从目标数组的指定索引处开始,将全部 StringCollection 值复制到一维字符串数组中

IndexOf

搜索指定的字符串并返回 StringCollection 内的第一个匹配项的从零开始的索引

Insert

将字符串插入 StringCollection 中的指定索引处

Remove

StringCollection 中移除特定字符串的第一个匹配项

RemoveAt

移除 StringCollection 的指定索引处的字符串

CodeSmith实用技巧(二):使用FileNameEditor

FileNameEditor类给我们提供了在CodeSmith属性面板中弹出打开或保存文件对话框的方式,在使用时,首先在模版中得添加对程序集CodeSmith.CustomProperties的引用。然后就可以在模版中定义一个属性来使用FileNameEditor

 1 <script runat="template">

 3 private string _userFileName = @"c:\temp\test.txt";
 4 [Editor(typeof(FileNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 8  Category("Custom"), Description("User selected file.")]
10 public string UserFileName {
16       get  {return _userFileName;}
18       set  {_userFileName= value;}
20 }
223 </script>

当我们执行该模版时,在属性面板中同样显示为一个按钮:

单击该按钮,弹出一个保存文件的对话框:

我们也可以通过FileDialogAttribute来自定义弹出的对话框,修改模版为:

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

弹出的对话框如下所示:

当我们想用一个文件夹的名称来代替文件时,可以使用FolderNameEditor类。

 1 <%@ Assembly Name="System.Design" %>
 2 <script runat="template">
 3 private string _outputDirectory = @"c:\temp"; 4 [Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 5 Category("Custom"), Description("Output directory.")]
 6 public string OutputDirectory
 7 {
 8        get  {return _outputDirectory;}
 9        set  {_outputDirectory= value;}
10 }
11 </script>

FileNameEditor重要方法和属性介绍:

公共方法:

名称

描述

EditValue

使用由 GetEditStyle 方法提供的编辑器样式编辑指定的对象

GetEditStyle

获取 EditValue 方法所使用的编辑样式

CodeSmith实用技巧(三):使用FileDialogAttribute

  使用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”。

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

执行后弹出的对话框界面如下:

CodeSmith实用技巧(四):使用扩展属性

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

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

CodeSmith定义的扩展属性包括table columns, view columns, command parameters

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生成一个基类,然后自定义其它类继承于该类。当我们重新生成基类时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 %>
    }
}

执行该模版并输入如下数据:

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

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

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

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

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

CodeSmith实用技巧(六):使用XML 属性

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>

这是一个简单的带有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>

生成后的代码如下:

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 ." %>
<%@ XmlProperty Name="TargetFile" Optional="False" Category="Data" Description="XML file to iterat" %>
<%@ 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实用技巧(七):从父模版拷贝属性

 在使用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实用技巧(八):生成的代码输出到文件中

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")]
publicoverride string OutputFile
{
    
get  {return base.OutputFile;}
    
set  {base.OutputFile = value;}
}
</script>

CodeSmith实用技巧(九):重载Render方法来控制输出

 CodeSmith中,CodeTemplate.Render方法是在模版执行完成进行模版输出时执行,你可以通过重载CodeTemplate.Render方法来修改CodeSmith输出时的事件处理。例如:你可以修改模版输出时的方式来代替现在默认的方式,下面这段代码展示了在保持CodeSmith默认的窗口显示的同时,把结果输出到两个不同的文件。

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

注意不能忘了base.Render(writer);这句话,否则你将不能获得默认的输出。当重载CodeTemplate.Render方法时,你也可以访问TextWriter,也就是说你也可以直接添加其它的附属信息到模版输出的内容中。

CodeSmith实用技巧(十):通过编程执行模版

CodeSmith在执行模版时通过调用一些API来完成的,主要经过了以下这几步的操作:

l         编译一个模版

l         显示编译错误信息

l         创建一个新的模版实例

l         用元数据填充模版

l         输出结果

下面这段代码显示了这些操作:

CodeTemplateCompiler compiler = new CodeTemplateCompiler("..\\..\\StoredProcedures.cst");
compiler.Compile();  
if (compiler.Errors.Count == 0)
{
    CodeTemplate template = compiler.CreateInstance();  
    DatabaseSchema database = 
new DatabaseSchema(new SqlSchemaProvider(), 

@"Server=(local)\NetSDK;Database=Northwind;Integrated Security=true;");
    TableSchema table = database.Tables["Customers"]; 
    template.SetProperty("SourceTable", table);
    template.SetProperty("IncludeDrop", 
false);
    template.SetProperty("InsertPrefix", "Insert");

 template.Render(Console.Out);
}
else
{
    
for (int i = 0; i < compiler.Errors.Count; i++)
    
{
        Console.Error.WriteLine(compiler.Errors[i].ToString());
    }
}

在这里我们用了Render方法,其实CodeTemplate.RenderToFileCodeTemplate.RenderToString方法可能更有用,它可以直接让结果输出到文件中或赋给字符型的变量。

CodeSmith实用技巧(十一):添加设计器的支持

如果你需要提供一个复杂的组合用户界面来输入元数据,这时就要添加设计器的支持。换句话说,除此之外没有别的办法来输入你自定义的元数据类型。添加设计器的支持,首先你要创建一个Editor作为自定义的类型,一个Editor其实就一个继承于.NET 中的System.Drawing.Design.UITypeEditor类的子类。

安装CodeSmith后在,在C:\Program File\CodeSmith\ SampleProjects 文件夹下有很多SampleCustomProperties的工程。例如:DropDownEditorProperty是一个把字符串和布尔类型的值结合在一起的元数据,它提供了一个类DropDownEditorPropertyEditor继承于System.Drawing.Design.UITypeEditor

[Editor(typeof(CodeSmith.Samples.DropDownEditorPropertyEditor), typeof(System.Drawing.Design.UITypeEditor))]
publicclass DropDownEditorProperty

在使用的时候跟其它的元数据类型是一样,不过别忘记添加对程序集的引用,引用CodeSmith默认的是不认识该类型的。

<%@ Property Name="DropDownEditorProperty" Type="CodeSmith.Samples.DropDownEditorProperty" Category="Options" Description="This property uses a custom dropdown editor."%>
<%@ Assembly Name="SampleCustomProperties" %>

当用户想要编辑DropDownEditProperty时,单击CodeSmith属性面板将会显示如下的自定义对话框:

CodeSmith实用技巧(十二):自动执行SQL脚本

CodeSmith中,如果生成的代码是SQL脚本,则可以在生成代码完成时自动执行生成的代码,也就是在生成的SQL脚本的同时在数据库中创建新的对象。

BaseTemplates.ScriptUtility对象提供ExecuteScript方法可以实现,如果想在生成代码完成后立即执行生成的脚本,可以很方便的通过重载OnPostRender来实现。

在使用之前,先添加对下列程序集的引用:

<%@ Assembly Name="CodeSmith.BaseTemplates"%>
<%@ Import Namespace="CodeSmith.BaseTemplates" %>

看下面的这个例子:

protected override void OnPostRender(string result) 
{
    
// execute the output on the same database as the source table.
    CodeSmith.BaseTemplates.ScriptResult scriptResult = 
     CodeSmith.BaseTemplates.ScriptUtility.ExecuteScript(
this.SourceTable.Database.ConnectionString, 
     result, 
new System.Data.SqlClient.SqlInfoMessageEventHandler(cn_InfoMessage)); 
    Trace.Write(scriptResult.ToString());
    
base.OnPostRender(result);
}
在这个例子中SourceTable是一个类型为SchemaExplorer.TableSchema.的属性,使用的时候需要调整部分代码来获取数据库的连接以便在生成代码完成后执行脚本。

CodeSmith实用技巧(十三):使用CodeTemplateInfo对象

CodeSmith中使用CodeTemplateInfo可以获取当前模版的一些信息:

属性

返回值

CodeBehind   

Gets the full path to the code-behind file for the template (or an empty string if there is no code-behind file).

ContentHashCode

Gets the hash code based on the template content and all template dependencies.  

DateCreated

Gets the date the template was created.

DateModified

Gets the date the template was modified.  

Description

Gets the description.  

DirectoryName

Gets the name of the directory the template is located in.  

FileName

Gets the name of the template file.  

FullPath

Gets the full path to the template.  

Language

Gets the template language.  

TargetLanguage

Gets the target language.  

看一下一个具体的使用例子:

<%@ CodeTemplate Language="VB" TargetLanguage="Text" Description="Demonstrates CodeTemplateInfo." %>
<% DumpInfo() %>
<script runat="template">
Public Sub DumpInfo()
    Response.WriteLine("Template:        {0}", Me.CodeTemplateInfo.FileName)
    Response.WriteLine("Created:         {0}", Me.CodeTemplateInfo.DateCreated)
    Response.WriteLine("Description:     {0}", Me.CodeTemplateInfo.Description)
    Response.WriteLine("Location:        {0}", Me.CodeTemplateInfo.FullPath)
    Response.WriteLine("Language:        {0}", Me.CodeTemplateInfo.Language)
    Response.WriteLine("Target Language: {0}", Me.CodeTemplateInfo.TargetLanguage)
End Sub
</script>
执行该模版输出如下(环境不同,输出也不同):

Template:        CodeTemplateInfo.cst
Created:         6/29/20058:54:19 PM
Description:     Demonstrates CodeTemplateInfo.
Location:        C:\Program Files\CodeSmith\v3.0\SampleTemplates\Test\CodeTemplateInfo.cst
Language:        VB
Target Language: Text

CodeSmith实用技巧(十四):使用Progress对象

Progress对象可以在CodeSmith生成代码时给用户显示一个进度条,当生成代码的时间很长时非常有用。如果你使用的是CodeSmith Explorer,进度条将显示在Generate按钮的左边:

如果使用的是CodeSmith Studio,进度条将显示在状态栏上:

使用Progress和在WinForm中使用进度条差不多,需要设置它的最大值和步长:

this.Progress.MaximumValue =25;
this.Progress.Step = 1;

如果想显示出进度,需要调用PerformStep方法:

this.Progress.PerformStep();

CodeSmith实用技巧(十五):使用快捷键

CodeSmith中,以下几个快捷键有助于我们快速输入。

1Ctrl + Shift + C

在空行上,按下Ctrl + Shift + C后将会录入一个代码块。

<%  %>

 2Ctrl + Shift + Q

按下Ctrl + Shift + Q后录入一个脚本块。

<script runat="template">
</script>

3Ctrl + Shift + V

对代码块反转,如有下面这样一行代码:

<%for(int i=0;i<10;i++) {}%>

在两个大括号之间按下Ctrl + Shift + V后,将变成如下代码:

<%for(int i=0;i<10;i++) {%>  <%}%>

4Ctrl + Shift + W

按下Ctrl + Shift + W后会录入一个输出的代码块:

<%=  %>

注意:在使用快捷键的时候,如果想要把一段代码之间放在录入的标记中间,首先选中这些代码,再按下快捷键组合。比如我们有一段这样的代码,想把它放在<script>里面。

public enum CollectionTypeEnum { Vector, HashTable, SortedList}
public override void Render(TextWriter writer) {
    StreamWriter fileWriter1 = 
new StreamWriter(@"C:\test1.cs", true);
    
this.Response.AddTextWriter(fileWriter1);
    StreamWriter fileWriter2 = 
new StreamWriter(@"C:\test2.cs", true);
    
this.Response.AddTextWriter(fileWriter2);
    
base.Render(writer);
   fileWriter1.Close();
    fileWriter2.Close();
}
选中它,再按下Ctrl + Shift + Q后就会变成:

<script runat="template">
publicenum CollectionTypeEnum {  Vector,  HashTable,  SortedList}
public override void Render(TextWriter writer)
{
    StreamWriter fileWriter1 = 
new StreamWriter(@"C:\test1.cs", true);
    
this.Response.AddTextWriter(fileWriter1);
    StreamWriter fileWriter2 = 
new StreamWriter(@"C:\test2.cs", true);
    
this.Response.AddTextWriter(fileWriter2);
    
base.Render(writer);

    fileWriter1.Close();
    fileWriter2.Close();
}
</script>

 

 

 

posted on 2006-06-20 11:14  灵风  阅读(972)  评论(0编辑  收藏  举报