code smith 使用介绍

利用CodeSmith为SQL Server CE生成项目代码
 
摘要:CodeSmith是很多.NET开发人员至爱的开发辅助工具,它能够使开发人员从大量枯燥无味的重复编码中解脱,集中精力解决实际业务问题和技术问题。本文将介绍如何将CodeSmith用于Windows Mobile项目,以SQL Server Compact Edition数据库作为代码生成的依据生成项目代码。

什么是代码生成器?
代码产生器是产生式编程(Generative Programming)在实际应用中的一种产物。它以系统建模为基础,通过抽象各种系统间的共性与特性,利用代码模板和组件重用技术,自动产生满足客户需求的软件产品。从而降低成本,减少软件推向市场的时间,并且保证更好的产品质量。最终取得规模经济和范围经济的优点。2004年我还在大学读书的时候曾开发过一个基于模板引擎的代码生成器——RapidTier,当时这个作品还获得了广东省高校杯软件设计大赛的二等奖。在.NET的世界里,目前最有名的代码生成器当属CodeSmith和MyGeneration。这两款代码生成器都是基于模板引擎的,使用起来方便灵活,而且模板资源非常丰富。

CodeSmith 简介
CodeSmith 是一个基于模板的代码生成器,你可以利用它来生成任何文本语言的代码。CodeSmith 生成的代码可以通过模板的属性来定制。CodeSmith 模板的语法跟 ASP.NET 非常相似,你可以在模板中使用 C# 或 VB.NET 控制代码的生成。通常,开发人员利用CodeSmith根据SQL Server或Oracle等大型数据库生成各种项目代码(如:存储过程、数据访问层、业务逻辑层、表现层等)。今天将向各位介绍如何利用 CodeSmith为移动数据库SQL Server Compact Edition生成Windows Mobile项目的代码。

配置SchemaProvider
CodeSmith通过SchemaProvider来支持各种数据库。在CodeSmith Professional 4.1.2安装后,默认只支持SQL Server、Oracle、Access、MySQL等数据库类型。如果需要支持其他类型的数据库,可以到网上搜索相关数据库的 SchemaProvider实现,或者自己手动编写代码实现ISchemaProvider接口。
最近,我从网上找到了SQL Server Compact Edition(3.1)的SchemaProvider实现,经过代码调整和调试,现在跟大家分享一下。可以从这里下载到这个SchemaProvider相关的DLL,下载后将其解压,并将 SchemaExplorer.SqlCeSchemaProvider.dll和System.Data.SqlServerCe.dll文件复制到 CodeSmith的SchemaProvider目录下(C:/Program Files/CodeSmith/v4.1/SchemaProviders)。

配置数据源
启动CodeSmith,点击左边停靠的Schema Explorer窗口上方点击“Manage Data Sources”工具栏按钮,打开Data Source Manager窗口。

Data Source Manager窗口打开后,点击Add按钮添加新的数据源。在Data Source窗口中,数据源名称(Name)输入“Northwind sqlce”,提供程序类型(Provider Type)选择SqlCeSchemaProvider,连接语句输入“data source=c:/Northwind.sdf”,假设你已经将SQL Server Compact Edition自带的Northwind.sdf数据库复制到C盘根目录了。

你可以通过点击Test按钮测试一下是否正常连接,然后点击OK保存数据源,回到Data Source Manager窗口,现在看到多了一个叫“Northwind sqlce”的数据源了。

“Northwind sqlce”数据源已经添加成功,点击Close按钮关闭Data Source Manager窗口。回到Schema Explorer窗口,展开“Northwind sqlce”数据源,浏览各个表的字段和属性。

生成代码
在CodeSmith右边停靠的Template Explorer窗口打开自带的模板“CodeSmith 4.1 Samples/ActiveSnippets/CSharp/TableProperties.cst”。这个模板可以从一个数据库的表的所有字段生成对应的实体类的所有属性(Property)定义代码。
模板被打开后,在CodeSmith右边停靠的Properties窗口选择SourceTable属性,点击旁边的“...”按钮浏览并选择一个Northwind.sdf数据库的表。这里我们选择Categories表,并点击Select按钮确定。

现在可以按F5生成代码了,生成的结果如下所示:

private int _categoryID;

public int CategoryID
{
    get { return _categoryID; }
    set { _categoryID = value; }
}

private string _categoryName;

public string CategoryName
{
    get { return _categoryName; }
    set { _categoryName = value; }
}

private string _description;

public string Description
{
    get { return _description; }
    set { _description = value; }
}

private System.Byte[] _picture;

public System.Byte[] Picture
{
    get { return _picture; }
    set { _picture = value; }
}
你还可以选择其他的表或其他模板生成代码试一试,体验一下CodeSmith的强大之处。

总结
通过上面的介绍和示例演示,相信大家都认同CodeSmith确实很好很强大。当然,这里只是演示了一个很简单的例子,你可以根据项目的实际需要自己编写模板,按自己的方式去生成项目代码。编写模板最快捷的方法就是基于现有比较类似的模板进行修改。CodeSmith之所以能够用于SQL Server Compact Edition数据库的代码生成,除了前面提到的它通过SchemaProvider支持各种类型的数据库,还有一点很重要的就是SQL Server Compact Edition支持桌面平台,如果是SQL Server Mobile就没有办法做到这一点了。
相关下载:SqlCeSchemaProvider.rar

http://upto.cnblogs.com/

========

code Smith 使用学习

CodeSmith在执行模版时通过调用一些API来完成的,主要经过了以下这几步的操作:
         编译一个模版
         显示编译错误信息
         创建一个新的模版实例
         用元数据填充模版
         输出结果
下面这段代码显示了这些操作:
 
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());
    }
}
 
如果你需要提供一个复杂的组合用户界面来输入元数据,这时就要添加设计器的支持。换句话说,除此之外没有别的办法来输入你自定义的元数据类型。添加设计器的支持,首先你要创建一个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))]
public class 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脚本,则可以在生成代码完成时自动执行生成的代码,也就是在生成的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可以获取当前模版的一些信息:
属性

返回值

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/2005 8:54:19 PM
Description:     Demonstrates CodeTemplateInfo.
Location:        C:/Program Files/CodeSmith/v3.0/SampleTemplates/Test/CodeTemplateInfo.cst
Language:        VB
Target Language: Text
 
Progress对象可以在CodeSmith生成代码时给用户显示一个进度条,当生成代码的时间很长时非常有用。如果你使用的是CodeSmith Explorer,进度条将显示在Generate按钮的左边:

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

使用Progress和在WinForm中使用进度条差不多,需要设置它的最大值和步长:
this.Progress.MaximumValue = 25;
this.Progress.Step = 1;
如果想显示出进度,需要调用PerformStep方法:
this.Progress.PerformStep();
 
在CodeSmith中,以下几个快捷键有助于我们快速输入。
1.Ctrl + Shift + C
在空行上,按下Ctrl + Shift + C后将会录入一个代码块。
<%  %>
 2.Ctrl + Shift + Q
按下Ctrl + Shift + Q后录入一个脚本块。
 
<script runat="template">

</script>

3.Ctrl + Shift + V
对代码块反转,如有下面这样一行代码:
<% for(int i=0;i<10;i++){}%>
在两个大括号之间按下Ctrl + Shift + V后,将变成如下代码:
<% for(int i=0;i<10;i++){%>  <%}%>
4.Ctrl + 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">
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();
}

</script>
========

CodeSmith的基础模版类

基础模版类
类型描述: 
Batch      
OutputFileCodeTemplate  模版通过继承此类能够在生成过程中把他们的输出保存到文件中 
ScriptError    在脚本执行中出现一个错误
ScriptErrorCollection   
ScriptResult    一个脚本的运行结果包含一些已经发生的错误
ScriptUtility    这个类能用来在数据库上执行Sql脚本。
SqlCodeTemplate   继承此类的模版当从一个Sql数据源生成代码时能够获得很多有用的帮助方法
StringUtility    多种处理string型的方法
各类型下的成员属性及方法
Batch Class
属性
Content   
LineCount   
StartLineNumber 
方法
Finalize 在一个对象再次创建之前获得空闲资源并且执行其他的清空操作
MemberwiseClone 建立现有对象的副本
OutputFileCodeTemplate Class
属性
CodeTemplateInfo  得到当前模版的信息
OutputFile  此属性用来指定一个保存模版输出的输出文件名
Progress   提供一种方式汇报模版的执行进程
Response   模版输出返回流。此属性可以在程序中写出流
State   模版实例的状态
ValidationErrors  得到模版的错误
方法
CopyPropertiesTo  把匹配的属性拷贝到另一个代码模版实例中
GetCodeTemplateInstance 重载,得到指定模版的实例
GetFileName  为模版的输出得到一个默认的名字
GetProperties   得到模版的所有属性
GetProperty   得到模版的指定属性
GetRequiredProperties  得到模版上所有必要的属性
GetType   得到当前实例类型
ParseDefaultValue  解析属性的默认值
SavePropertiesToXml  以XML保存属性
SavePropertiesToXmlFile 保存属性到一个XML文档
SetProperty   重载,保存指定的属性值
ToString
ScriptError Class
属性
方法
Finalize 在一个对象再次创建之前获得空闲资源并且执行其他的清空操作
MemberwiseClone 建立现有对象的副本
ScriptUtility Class
属性
ConnectionString 执行脚本时使用此连接字符串
Script   执行的脚本
方法
ExecuteScript  重载,执行脚本
SqlCodeTemplate Class
属性
CodeTemplateInfo  得到当前模版的信息
OutputFile  此属性用来指定一个保存模版输出的输出文件名
Progress   提供一种方式汇报模版的执行进程
Response   模版输出返回流。此属性可以在程序中写出流
State   模版实例的状态
ValidationErrors  得到模版的错误
方法
CopyPropertiesTo  把匹配的属性拷贝到另一个代码模版实例中
GetCamelCaseName Returns a camel cased name from the given identifier. 
GetCodeTemplateInstance 重载,得到指定模版的实例
GetCSharpVariableType 基于给定列返回C#的变量类型
GetFileName  为模版的输出得到一个默认的名字
GetMemberVariableDeclarationStatement
   重载,返回C#成员变量声明语句
GetMemberVariableDefaultValue
   基于一个列的数据类型返回一个默认值
GetMemberVariableName 为一个给定标示返回一个C#成员变量名
GetProperties   得到模版的所有属性
GetProperty   得到模版的指定属性
GetPropertyName  返回指定列的公有属性的名字
GetReaderMethod  Returns the name of the typed reader method for a given column. 
GetRequiredProperties  得到模版上所有必要的属性
GetSpacedName  Returns a spaced out version of the identifier.
GetSqlDbType  返回一个给定列的SqlDbType
GetSqlParameterExtraParams
   为ADO的参数声明生成额外的参数
GetSqlParameterStatement
   重载,返回给定列的T-Sql的参数声明
GetSqlParameterStatements
   重载,给指定列加一个参数到ADO对象生成一个指定声明(Generates an assignment statement that adds a parameter to a ADO object for the given column. )
GetValidateStatements 基于某列生成一组确认声明
IncludeEmptyCheck 确定一个给定列是否可以为空
IncludeMaxLengthCheck 确定一个给定列的类型是否需要最大长度的定义
IsUserDefinedType 确定是否一个给定列用了一个UDT(用户定义类型)
ParseDefaultValue  解析属性的默认值
SavePropertiesToXml  以XML保存属性
SavePropertiesToXmlFile 保存属性到一个XML文档
SetProperty   重载,保存指定的属性值
========

CodeSmith 使用实例

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。
模版代码如下:
<%@ CodeTemplate Language="C#" TargetLanguage="C#" %>
<%@ Assembly Name="CodeSmith.CustomProperties" %>
<%@ Property Name="List" Type="CodeSmith.CustomProperties.StringCollection" Category="Custom" Description="This is a sample StringCollection" %>
using System;
namespace Test
{       
         /** <summary>
         ///     测试StringCollection
         /// </summary>
         public class Test
         {
                   public static void Main(string[] args)
                   {
                            <%for(int i = 0;i<List.Count;i++){%>
                            Console.WriteLine(<%=List[i]%>);
                            <%}%>
                   }
         }
}
 
成后的代码:
using System;
namespace Test
{       
         /** <summary>
         ///     测试StringCollection
         /// </summary>
         public class Test
         {
                   public static void Main(string[] args)
                   {
                            Console.WriteLine(Apples);
                            Console.WriteLine(Fish);
                   }
         }
}
  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 实例2

FileNameEditor类给我们提供了在CodeSmith属性面板中弹出打开或保存文件对话框的方式,在使用时,首先在模版中得添加对程序集CodeSmith.CustomProperties的引用。然后就可以在模版中定义一个属性来使用FileNameEditor:
 
 1<script runat="template">
 2
 3private string _userFileName = @"c:/temp/test.txt";
 4
 5 
 6
 7[Editor(typeof(FileNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 8
 9Category("Custom"), Description("User selected file.")]
10
11 
12
13public string UserFileName
14
15{
16
17      get {return _userFileName;}
18
19      set {_userFileName= value;}
20
21}
22
23</script>
24
25
当我们执行该模版时,在属性面板中同样显示为一个按钮:

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

我们也可以通过FileDialogAttribute来自定义弹出的对话框,修改模版为:
 
 1private string _openFileName = @"c:/temp/test.txt";
 2
 3
 4[Editor(typeof(FileNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 5
 6FileDialogAttribute(FileDialogType.Open, Title="Select Input File"),
 7
 8Category("Custom"), Description("User selected file.")]
 9
10 
11
12public string OpenFileName
13
14{
15
16      get {return _openFileName;}
17
18      set {_openFileName= value;}
19
20}
21
22
弹出的对话框如下所示:

当我们想用一个文件夹的名称来代替文件时,可以使用FolderNameEditor类。
 
 1<%@ Assembly Name="System.Design" %>
 2<script runat="template">
 3private string _outputDirectory = @"c:/temp";
 4[Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor)),
 5Category("Custom"), Description("Output directory.")]
 6public string OutputDirectory
 7{
 8       get {return _outputDirectory;}
 9       set {_outputDirectory= value;}
10}
11</script>
12
13
FileNameEditor重要方法和属性介绍:
公共方法:
名称
描述
EditValue
使用由 GetEditStyle 方法提供的编辑器样式编辑指定的对象
GetEditStyle
获取 EditValue 方法所使用的编辑样式
========

CodeSmith应用实例(一)

版权声明:本文为博主原创文章,未经博主允许不得转载。

一、一个简单的例子
 
       这个例子仅是一个简单的应用,在我翻译并学习完CodeSmith的英文帮助文档后,对CodeSmith有了一定的了解,开始着手编写一些CodeSmith应用模板,今天按照最早提到的例子自行编写了一个基于表的添加存储过程的生成模板。具体语法前面基础中已做过详细解释这里仅是一个小综合应用的例子,望对大家学习CodeSmith有很好的帮助。我的同事也写了几个CodeSmith的技巧的文章http://terrylee.cnblogs.com/大家有空去看看,写的很不错哦,都是针对于CodeSmith自定义属性编写的东东:)
 1<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL" Description="Create a procedure which have insert function base on a table." %>
 2<%@ Assembly Name="SchemaExplorer" %>
 3<%@ Import Namespace="SchemaExplorer" %>
 4<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="DataTable" Description="Table that the stored procedures should be based on." %>
 5<%@ Property Name="Author" Type="String" Category="Context" Description="The author for this procedure."%>
 6<%@ Property Name="Description" Type="String" Category="Context" Description="The description for this procedure."%>
 7<script runat="template">
 8public string GetSqlParameterStatement(ColumnSchema column)
 9{
10    string param = "@" + column.Name + " " + column.NativeType;
11    switch (column.DataType)
12    {
13        case DbType.Decimal:
14        {
15            param += "(" + column.Precision + ", " + column.Scale + ")";
16            break;
17        }
18        default:
19        {
20            if (column.Size > 0)
21            {
22                param += "(" + column.Size + ")";
23            }
24            break;
25        }
26    }
27    return param;
28}
29</script>
30CREATE PROCEDURE dbo.<%=SourceTable.Name %>Insert
31/*
32==================================================
33Author:<%= Author %>
34CreatedTime:<%= System.DateTime.Now.ToShortDateString() %>
35Description:<%= Description %>
36==================================================
37*/
38<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
39<%= GetSqlParameterStatement(SourceTable.Columns[i]) %><% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>    <% if (SourceTable.Columns[i].Description != "") { %>--<%= SourceTable.Columns[i].Description %><% } %>
40<% } %>
41AS
42Insert Into [<%= SourceTable.Name %>] 
43(
44<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
45[<%= SourceTable.Columns[i].Name %>]<% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>    <% if (SourceTable.Columns[i].Description != "") { %>--<%= SourceTable.Columns[i].Description %><% } %>
46<% } %>
47)
48Values
49(
50<% for (int i = 0; i < SourceTable.Columns.Count; i++) { %>
51@<%= SourceTable.Columns[i].Name %><% if (i < SourceTable.Columns.Count - 1) { %>,<% } %>
52<% } %>
53)
二、具有删除功能的模板

今天又根据CodeSmith的几个基本组件写出了基于表生成删除功能的存储过程代码生成模板。
        昨天觉得添加的存储过程模板写的比较简单,今天准备详细介绍一下这个删除的模板。
        首先介绍我们使用到的一个教本函数GetSqlParameterStatement(ColumnSchema column),其函数代码如下:

1public string GetSqlParameterStatement(ColumnSchema column)
 2{
 3    string param = "@" + column.Name + " " + column.NativeType;
 4    switch (column.DataType)
 5    {
 6        case DbType.Decimal:
 7        {
 8            param += "(" + column.Precision + ", " + column.Scale + ")";
 9            break;
10        }
11        default:
12        {
13            if (column.Size > 0)
14            {
15                param += "(" + column.Size + ")";
16            }
17            break;
18        }
19    }
20    return param;
21}

大家可以看到,这个函数需要传入一个ColumnSchema类型的参数,它代表一个数据表中的列,并且是一个列,然后根据ColumnSchema这个类具有的属性,对传入的列进行一些操作然后返回我们生成存储过程时需要的代码。
        首先介绍一下ColumnSchema的一些常用属性,如下表: 
属性Property

描述Description

AllowDBNull

是否允许空值NULL

Database

通过DatabaseSchema对象得到当前列所属的数据库

DataType

此数据对象的数据类型

Description

当前对象的描述

ExtendedProperties

用来存储SchemaObject的其他附加信息

IsForeignKeyMember

当前列是否为外键

IsPrimaryKeyMember

当前列是否为主键

IsUnique

当前列是否唯一

Name

列的名称

NativeType

列定义的数据类型

Precision

数据对象的精度

Scale

数据对象的范围(个人理解为需要保留小数的范围)

Size

数据对象的大小(例如:字符串长度为10)

SystemType

数据对象的系统类型

Table

当前列所属的数据表

下面为我们首先要生成存储过程,要自动生成的代码分成了红、绿、蓝三部分。
CREATE PROCEDURE dbo.CustomersDelete
/*
==================================================
Author:Bear-Study-Hard
CreatedTime:2005-12-28
Description:Delete a record from table Customers
==================================================
*/
@CustomerID nchar(5) --客户ID
AS
Delete From [Customers]
Where
[CustomerID] = @CustomerID

我们的这个脚本函数就是要实现拼出红色的部分,GetSqlParameterStatement函数接收到ColumnSchema类型的参数后,从其Name属性和NativeType属性拼出@CustomerID nchar部分,然后由于不同的数据类型尤其是数值类型和字符串类型的区别,会导致数据类型的大小会有所不同,这里仅对Decimal的数据类型进行了判断(Numeric和float等均需要这种处理),然后根据Precision属性得到精度并通过Scale属性得到了需要保留小数的范围。如果传出的为非Decimal类型字段则直接通过Size属性取出其大小即可。得到了(5)部分。最后的注释是为了生成的存储过程解读性好加上的,使用的是Description属性。
    剩下的绿色部分和蓝色部分生成时比较简单,请各位自行学习。模板代码为:

1<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL" Description="Create a procedure which have delete function base on a table.Must use PrimaryKey to delete a record." %>
 2<%@ Assembly Name="SchemaExplorer" %>
 3<%@ Import Namespace="SchemaExplorer" %>
 4<%@ Property Name="SourceTable" Type="SchemaExplorer.TableSchema" Category="DataTable" Description="Table that the stored procedures should be based on." %>
 5<%@ Property Name="Author" Type="String" Category="Context" Description="The author for this procedure." Optional="true"%>
 6<%@ Property Name="Description" Type="String" Category="Context" Description="The description for this procedure." Optional="true"%>
 7<script runat="template">
 8public string GetSqlParameterStatement(ColumnSchema column)
 9{
10    string param = "@" + column.Name + " " + column.NativeType;
11    switch (column.DataType)
12    {
13        case DbType.Decimal:
14        {
15            param += "(" + column.Precision + ", " + column.Scale + ")";
16            break;
17        }
18        default:
19        {
20            if (column.Size > 0)
21            {
22                param += "(" + column.Size + ")";
23            }
24            break;
25        }
26    }
27    return param;
28}
29</script>
30CREATE PROCEDURE dbo.<%=SourceTable.Name %>Delete
31/*
32==================================================
33Author:<%= Author %>
34CreatedTime:<%= System.DateTime.Now.ToShortDateString() %>
35Description:<%= Description %>
36==================================================
37*/
38<% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
39<%= GetSqlParameterStatement(SourceTable.PrimaryKey.MemberColumns[i]) %><% if (i < SourceTable.PrimaryKey.MemberColumns.Count - 1) { %>,<% } %>    <% if (SourceTable.Columns[i].Description != "") { %>--<%= SourceTable.Columns[i].Description %><% } %>
40<% } %>
41AS
42Delete From [<%= SourceTable.Name %>] 
43Where
44<% for (int i = 0; i < SourceTable.PrimaryKey.MemberColumns.Count; i++) { %>
45<% if (i > 0) { %>AND <% } %>[<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>] = @<%= SourceTable.PrimaryKey.MemberColumns[i].Name %>
46<% } %>

如果有问题我会尽力帮助大家解决的,共同提高^_^

本文永久地址: http://www.livebaby.cn/blog/u/meil/archives/2007/984.html
 
========

CodeSmith使用基础教程 四 — 控制台与属性编辑器

七、CodeSmith控制台指南。

很多人仅仅知道CodeSmith像一个图形应用程序,或者可能是一个Visual Studio的附件,但是通过CodeSmith的控制台应用程序还有好多其他的使用方法。控制台应用程序是很有价值的,因为可以通过它去生成脚本,或者其他一些自动工具。这篇文档的目的就是要告诉你怎样使用它的控制台应用程序并且如何去定义变量和参数。

Basic Usage

大多数情况下是用控制台应用程序来创建一个模板,一个属性文件,然后保存输出的文件。这有一个很好的例子介绍将合并模版的处理过程放到一个过程中,就像使用NAnt工具。

首先我们要确定完成一个什么样的模版,为这个模板创建一个什么样的XML属性文件。XML属性文件提供在执行模版是需要的各个属性。生成一个属性文件最简单的方法是在CodeSmith Explorer中打开一个模版,填写属性,点击生成按钮generate,然后再点击Save Property Set XML按钮。这个按钮会在点击完生成按钮后找到,在Save Output和Copy Output按钮旁边。然后系统提示输入保存XML属性文件的文件名,下面看一个ArrayList.cst模版创建的XML属性文件。

1<?xml version="1.0" encoding="us-ascii"?>
 2<codeSmith>
 3            <propertySet>
 4                        <property name="Accessibility">Public</property>
 5                        <property name="ClassName">PersonArray</property>
 6                        <property name="ItemType">Person</property>
 7                        <property name="ItemValueType">False</property>
 8                        <property name="ItemCustomSearch">False</property>
 9                        <property name="KeyName">PersonID</property>
10                        <property name="KeyType">int</property>
11                        <property name="IncludeInterfaces">True</property>
12                        <property name="IncludeNamespaces">False</property>
13            </propertySet>
14</codeSmith>
就像看到的一样,也可以手动创建这个文件,但是使用CodeSmith Explorer会更简便。

现在我们有了这个XML文件,我们继续看一下如何去执行这个模版并是用控制台工具保存结果。首先我们需要是用/template参数去声明我们要是用的模版,像这样:

C:/Program Files/CodeSmith/v3.0>cs /template:Samples/Collections/ArrayList.cst

在这个例子中我们使用了ArrayList.cst模版,它存储在本地的Samples/Collections文件夹下。下一步我们要去声明我们在最后一步需要创建的XML文件,我们是用/propertyset参数去实现。

C:/Program Files/CodeSmith/v3.0>cs /template:Samples/Collections/ArrayList.cst  /propertyset:PersonArray.xml

这个/property参数用来指定我们的XML属性文件。最后一个我们需要用的参数是/output参数,用来指定输出怎样被保存。

C:/Program Files/CodeSmith/v3.0>cs /template:Samples/Collections/ArrayList.cst /propertyset:PersonArray.xml /out:test.cs

使用/out参数指定将结果输出到一个叫test.cs文件中保存。执行这个命令后,模板将开始运行,使用属性文件将结果输出到test.cs文件保存。

这是大多数情况下有效使用控制台。

Merging Output

在各种代码生成中最大的挑战就是将生成的代码和开发人员编写或修改的代码区分开。控制台对这个问题提供了一个有效的独特的解决方案,使用一个指定的参数在当前已存在的代码文件中需要将模板生成的代码添加的地方指定一块区域。

下面是一个简单的代码文件,包含了我们要添加生成代码的区域。

1using System;
2
3namespace Entities
4{
5      GeneratedOrderEntity  
9}
我们的目标是将DatabaseSchema/BusinessObject.cst模版生成的代码添加到类文件的GeneratedOrderEntity区域中。和上一个例子一样,使用CodeSmith console控制台应用程序执行这个模版,但是这次要使用另一个参数merge。

C:/Program Files/CodeSmith/v3.0>cs /template:Samples/DatabaseSchema/BusinessObject.cst /propertyset:OrderEntity.xml /out:OrderEntity.cs /merge:InsertRegion= "RegionName=Sample Generated Region;Language=C#;"

使用merge参数我们可以指定区域的名称,在这个例子中是GeneratedOrderEntity,然后控制台应用程序将执行模版,并将结果添加到这个区域中。我们来看一下执行完这个指令后生成的代码。

1using System;
 2
 3namespace Infozerk.AuthServices.UnitTestSuite
 4{
 5      GeneratedOrderEntity就像看到的一样,Order类被添加到了我们指定的区域中。在代码文件中使用merge参数生成的内容在其他部分被修改或手写后很容易重新再次生成而不会产生影响。
 
参数介绍Parameter Reference

Specifying Output

/out:<file>

指定从模版创建的输出文件的名称。

/out:default

指定这个文件被默认保存成模版是用的名称。

/merge:<mergetype>=<init>

指定模版输出的区域。可以简写为/m

Specifying Input

/template:<file>

选择要执行的模版,简写为/t

/propertyset:<file>

生成代码时需要使用的XML属性文件。简写为/p

Compiler Options

/debug[+|-]

指定模版需要包含的调试信息。(允许在运行模版时进行调试)

/tempfiles[+|-]

指定保留临时文件。(如果在临时文件上调试也可以)

Miscellaneous

/help

显示帮助信息。

/nologo

禁止生成器版权信息。

八、编写CodeSmith自定义属性的编辑器(Writing Custom Property Editors)

当你开始编写自定义的CodeSmith模板时,很可能对于使用它的strings或integers属性很满意,但有时你会发现需要创建一个不同类型的属性,可能是一个自定义的类型或者是.NET framework中但是在属性面板中没有提供的类型。在模板中去作这些很简单,但是怎样指定一个类型在运行模板时显示在属性面板中呢?例如创建了一个Person类并且具有很多不同的属性,但是却没有办法让用户去组装这个类……除非创建一个自定义属性编辑器。

属性面板提供了方法去编写自定义的属性编辑器,当用户在面板上选择一个属性时可以激发相应的方法,同时也可以通过编写代码实现提示用户输入一个必要的值。下面我们举个例子,创建一个接受组建的属性并且是用影射循环贯串所有的类,是所有的类都可以使用它和它的方法,去创建一个NUnit测试基础。(这句翻译的不好,原文:As an example we are going to build a template which accepts an assembly as a property and then using reflection loops through all of the classes, and the methods of those classes, to build NUnit test stubs.)

首先,我们来关注一下模板的组件属性,暂且不看自定义编写的代码。模板的第一部分是一些声明定义和属性。将属性放在脚本标签中代替使用属性声明,在下一部分将看到这样做的必要。

1<%@ CodeTemplate Language="C#" TargetLanguage="C#" Description="Builds a class for each class in the assembly, and a test stub for every method." %>
 2
 3<%@ Import NameSpace="System.Reflection" %>
 4
 5<script runat="template">
 6
 7private Assembly assembly;
 8
 9public Assembly AssemblyToLoad
10{
11      get{return assembly;}
12      set{assembly = value;}
13}
14
15</script>

然后我们为组建assembly中的每一个类创建一个类,为每一个类创建他的方法。然后直接将模板的输出内容放入Visual Studio.NET,然后在编写组件的单元测试时使用向导。

1using System;
 2using NUnit.Framework;
 3
 4<%
 5      foreach(Type T in AssemblyToLoad.GetTypes())
 6      {
 7            if(T.IsClass)
 8            {
 9                  %>
10
11                  [TestFixture]
12                  public class <%=T.Name%>Tests
13                  {
14                  <%
15                              MethodInfo[] methods = T.GetMethods ( BindingFlags.Public | BindingFlags.Instance | BindingFlags.Static  );
16                              foreach(MethodInfo M in methods)
17                              {
18                                    %>
19
20                                    [Test]
21                                    public void <%=M.Name%>Test
22                                    {
23                                          //TODO Write this test
24                                    }                 
25                                    <%
26                              }
27
28                  %>}<%
29            }
30      }
31%>

/Files/Bear-Study-Hard/AssemblyHelper.zip

首先我们需要创建一个继承UITypeEditor的类。

1public class AssemblyFilePicker : UITypeEditor
2{
3      public AssemblyFilePicker(): base()
4      {
5      }
6}
 
        关于UITypeEditor的说明请大家参看MSDN或Visual Studio.NET自带帮助中的说明,其中有详细的例子。

然后我们需要重载UITypeEditor类的两个不同的方法。第一个需要重载点的方法是GetEditStyle,这个方法是告诉属性面板对于当前类型是用什么类型的编辑器,在这个例子中我们设置编辑类型为Modal。这样大家可以在该属性格子的右边看到一个小按钮,它将引发一个对话框等模式的对话(trigger a modal dialog)。这是我们的GetEditStyle方法:

1public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
2{
3      return UITypeEditorEditStyle.Modal;
4}

其中的Modal为显示一个省略号按钮。

首先我们要从当前的服务和控件中得到一个参考,有了控件的参考我们可以通过它转到ShowDialog方法。(原文:First we need to get a reference to the current service and control, we need the reference to the control so we can pass it to the ShowDialog method.)         然后我们创建一个openFileDialog类并填入适合的属性。        然后我们通过控件的参考(reference)将对话框显示给用户。        下一步我们检查用户是否点击了OK按钮,如果点击了,通过文件选择对话框选择文件后使用LoadForm方法加载这个组件,最后返回这个值。        这个值将被放在属性面板中并可以被模板读取,但是需要注意,在我们作这个之前要将组件import引入到模板中,并在模板中用一对属性声明。

1IWindowsFormsEditorService editorService = (IWindowsFormsEditorService)provider.GetService(typeof(IWindowsFormsEditorService));
2Control editorControl = editorService as Control;
3
4if (editorControl != null) 
5{

1OpenFileDialog openFileDialog = new OpenFileDialog();                         
2
3openFileDialog.CheckFileExists = true;
4openFileDialog.DefaultExt = ".dll";
5openFileDialog.Multiselect = false;
6openFileDialog.Title = "Select an Assembly:";
7openFileDialog.Filter = "Assembly Files | *.dll";

1DialogResult result = openFileDialog.ShowDialog(editorControl);

1if (result == DialogResult.OK)
 2            {
 3Assembly assembly = Assembly.LoadFrom( openFileDialog.FileName ) ;
 4                  value = assembly; 
 5            }
 6            else
 7            {
 8                  value = null;
 9            }
10      }
11}
12
13return value;
14}

加载这个模板我们仅需将这个组件assembly与模板放在同一目录下,然后再模板中加入下面两行代码。

1<%@ Assembly Name="AssemblyHelper" %>
2<%@ Import NameSpace="AssemblyHelper" %>

需要重载的另一个方法是EditValue方法,当用户电击属性时会调用这个方法。按照我们需要加载的组件类型需要创建一个打开文件对话框(open file dialog)然后捕获这个对话框,在属性格子中返回对话框的结果。

1public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value)
2{
3
4if (provider != null) 
5{
        这个模板仅仅可以编译通过,但是由于我们编写显示了一个类型属性面板并不知道如何去操作它,所以我们没有办法自定义指定组件在加载时想要加载的组件。

我们需要创建一个UITypeEditor,这是一个建立属性面板是用的特殊属性的类。UITypeEditor需要创建在一个和模板分离的组件中,我们是用Visual Studio创建这个类。

本文永久地址: http://www.livebaby.cn/blog/u/meil/archives/2007/982.html
========

实例演示CodeSmith与ECC开发模式结合---快速建站(一)

http://blog.csdn.net/breakersam/article/details/1551935
 
前言
       其实本文所说的思路产生以很久以前,本人也曾将用于多个小型项目开发之中,用下来的整体说还是比较满意。按理说,自己既然用了那么多次也应写些心得或是总结出来吧,无奈一是自己太懒二是文字功底有限,只好罢了!拖到了现在,方提指敲写,也不知成文怎样,由大家评说吧。
      本文作为开发笔记以流水的方式敲写,其中不讨论开发模式之间的优劣;如大家有好的建议也希望直面地提出来,我呢,以求进步!
文中所举的例子:ASP.NET (Net1.1)+ Access 基础上所搭建。
 
CodeSmith概述
       CodeSmith中文我不知叫什么,不太好解释,必竟这是“工业化”的东西,有点抽象,顾名思义(Code Smith 代码工匠),就是生成代码的东西;CodeSmith作用在于生成代码模板,减少手工书写代码的工作,提高生产效率,增加剥夺收入。习惯上,我们项目组里在应用CodeSmith有这着这样的感受:C#的语法,ASP的写法。不过话也得说回来,在ASP时代,我们没有这样的“艳遇”,那时代码的生成,只能在自己编写ASP Generator里生成,并且编写过程中也没有这么好的IDE支持。
        或许有人会这样认为,既然有了CodeSmith,那么好多逻辑不是一下子就可以生成了吗?干嘛要用什么ECC,烦!事实上,这话有部分多,也有大部分不对!是的,CodeSmith能快速地根据模板生成大量的代码,但不有能生成所有的代码,因为在一个逻辑必须根据具体的应用环境情况下随时变动逻辑的代码,其没有任何的意义可言。平时在开发过程中,我们也对没有接触过的CodeSmith的伙伴这样说:Code Smith 主要的是生成DAO(特别是与数据库的表中粒度一一对应的书写中)与相对稳定的应用对象逻辑代码,其不是万能的!生成的代码必须是软件开发过程中所已经协商好的开发模式的反映,而不是什么都要CodeSmith生成,否则生成的代码,谁也看不懂,更不用说维护了或是项目组内成员的学习了。
 
       下面我就简单提一下CodeSmith初学者经常提到了几个问题,至于CodeSmith具体是怎样应用的,我们可以查看其自带的学习例子或是在网上搜索,教程一大把。如下:
1.CodeSmith怎样与数据库结合
CodeTemplate里本身已经提供了访问了数据库的属性:
///
数据库的连接
 <%@ Property Name="SourceTable"                 Type="SchemaExplorer.TableSchema" Category="1. Context"
       Description="Table that the stored procedures should be based on." %>
在DataSource里Provider type t选择ADOXschemaProvider,输入类似的ConnectionString:Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:/开发项目/基于ACCESS的小型系统.NET/BreakerSimply/DataBase/BreakerSimply.mdb
//
表的访问
//writeable columns Data
#region IsWritableColumns
public string IsWritableColumns()
{
//把ID 排除
       string sTemp ="";
       foreach(ColumnSchema column in SourceTable.Columns)
       {
                     if (column.Name.ToLower()=="id")
                     {
                            }
                     else
                     {
                            sTemp +=this.GetPropertyName(column)+",";
                     }
       }
    return sTemp;
}
#endregion
 
public string GetNativeTypeString(ColumnSchema column)
{
       string sColumnType = "";
       string sTemp = column.NativeType.ToString();
       //Debug.Print(sTemp);
       //Response.WriteLine("{0}={1}", column.Name, sTemp);
       //Debugger.Break();
       sTemp = sTemp.ToLower();
       switch(sTemp)
       {
              case "advarwchar":
                     sColumnType = "OleDbType.VarWChar";
                     break;
              case "adinteger":
                     sColumnType = "OleDbType.Integer";
                     break;
              case "addate":
                     sColumnType = "OleDbType.Date";
                     break;
              case "adlongvarwchar":
                     sColumnType = "OleDbType.VarWChar";
                     break;
              case "adboolean":
                     sColumnType = "OleDbType.Boolean";
                     break;
              case "adcurrency":
                     sColumnType = "OleDbType.Currency";
                     break;
              case "float":
                     sColumnType = "OleDbType.Float";
                     break;
              case "image":
                     sColumnType = "OleDbType.Image";
                     break;
              case "int":
                     sColumnType = "OleDbType.Int";
                     break;
              case "money":
                     sColumnType = "OleDbType.Money";
                     break;
              case "nchar":
                     sColumnType = "OleDbType.NChar";
                     break;
              case "ntext":
                     sColumnType = "OleDbType.NText";
                     break;
              case "nvarchar":
                     sColumnType = "OleDbType.NVarChar";
                     break;
              case "real":
                     sColumnType = "OleDbType.Real";
                     break;
              case "smalldatetime":
                     sColumnType = "OleDbType.SmallDateTime";
                     break;
              case "smallint":
                     sColumnType = "OleDbType.SmallInt";
                     break;
              case "smallmoney":
                     sColumnType = "OleDbType.SmallMoney";
                     break;
              case "text":
                     sColumnType = "OleDbType.Text";
                     break;
              case "timestamp":
                     sColumnType = "OleDbType.Timestamp";
                     break;
              case "tinyint":
                     sColumnType = "OleDbType.TinyInt";
                     break;
              case "uniqueidentifier":
                     sColumnType = "OleDbType.UniqueIdentifier";
                     break;
              case "varbinary":
                     sColumnType = "OleDbType.VarBinary";
                     break;
              case "varchar":
                     sColumnType = "OleDbType.VarChar";
                     break;
              case "variantariant":
                     sColumnType = "OleDbType.Variantariant";
                     break;
              default:
                     sColumnType = "";
                     break;
       }
       return sColumnType;
}
 
2.CodeSmith生成后的代码存放。
如下
<script runat="template">
#region Template Property Script
private string _outputDirectory = String.Empty;
 
[Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string OutputFolder
{
 get
 {
    if (_outputDirectory.Length == 0)
       {
              string sOutputFolder = this.CodeTemplateInfo.DirectoryName;
              if(!sOutputFolder.EndsWith("//"))
                     sOutputFolder += "//";
             
              sOutputFolder += "Tempout//Model";
              if(!System.IO.Directory.Exists(sOutputFolder))
              {
                     System.IO.Directory.CreateDirectory(sOutputFolder);
              }
              return sOutputFolder;
       }
    return _outputDirectory;
 }
 set
 {
 if (value.EndsWith("//")) value = value.Substring(0, value.Length - 1);
 _outputDirectory = value;
 }
}
#endregion
</script>
CodeSmith软件自带了很多很好的例子,我也是从上面学的~~。
什么ECC
      ECC由Engine、Class、Collection三部分构成,Engine实际上是个控制器,负责怎样创建返回Class,Class表示现实世界的实体,具备详细的属性,Collection就是装载Class的集合容器了; ECC 有人称之为“与实现无关无关的应用框架”,或许这有点夸大之嫌,什么叫做“与实现无关”,晕死。ECC确实提供了松散耦合的体系结构,它的出现使被操作的对像之间更显得独立,更为清晰,并且在很大程度上也降低了业务与具体逻辑的耦合
在ASP.NET中,我们还得考虑这么个问题,数据控件的数据绑定问题:控件支持CollectionBase的绑定,支持自定义行为(特别跨对像之间的数据操作);这些都能在ECC的模式里得到良好的解决。
实例中的ECC架构
     本文将以一个具体的例子进行说明:(本想贴些图,但发现贴了好几次都不成功,只好罢了)
     这个例子主要是实现文章的管理,如分类与相关CRUD,也就是平时所说的做了个小小的新闻发布系统:栏目表(ArticleColumn) 与 Article表,两者是一对多的关系
ArticleColumn表结构
ID                                   自动编号
UUID                              UUID 
Name                               栏目名    
Class                               级数
Order                              排序
CreatedTime                    创建时间
IsActive                           是否启用
Article表结构
ID                                   自动编号
UUID                              UUID 
ColumnID                        栏目ID               
Title                                 标题   
Content                           内容
Author                             作者
CreatedTime                    创建时间
IsActive                           是否启用
      一般情况下,我是按这样的工作流程:
     1.              分析所要设计的系统有几个可以称为“对像”的元素;
     2.              接着,用toghter画一下设计下逻辑图,生成初步的“原始代码”;
     3.              在“原始代码”,添血加肉,完成初步的逻辑;
     4.              以上面的代码为骨架,在CodeSmith编写相应的代码。
     以纯粹文章功能模块为例:
ArticleMD (与数据库的ARTICLE表建立一一的映射,将reader读出数据装载入Article)
Article (继承MD,处理关联的对像数据,如在这里根据文章的ID获取该文章的栏目)
ArticleDAO (数据库访问逻辑,原始的CRUD操作逻辑)
ArticleBL (继承DAO,根据业务需要,对CRUD的操作进行进一步的封装)
ArticleCollection 基于CollectionBase,创建Aritlce集合;这个类可以从MSDN的例子获得。 
具体的码如下:
========

codesmith资料

http://www.cnblogs.com/Terrylee/archive/2005/12/28/306254.html
CodeSmith开发系列资料总结

http://www.tuicool.com/articles/2EbIra
CodeSmith自己动手写模板

http://www.cnblogs.com/whitewolf/archive/2010/09/27/1836729.html
CodeSmith模板引擎系列-目录

http://www.cnblogs.com/wintersun/p/3971072.html
软件代码生成之Codesmith模板.netTiers

http://www.cnblogs.com/knowledgesea/p/5016077.html
CodeSmith模板代码生成实战详解

http://blog.csdn.net/gxiangzi/article/details/6865619
CodeSmith .NET三层架构模板

codesmith学习总结相关推荐

  1. CodeSmith 学习资料收集

    CodeSmith开发系列资料总结: CodeSmith基础系列:         1.CodeSmith基础(一)         2.CodeSmith基础(二)         3.CodeSm ...

  2. 框架设计之菜鸟漫漫江湖路系列 二:自学求索

    二:自学求索 到处求索,勤习武功,略有所成,初会ObjectDataSource+CodeSmith+实体框架 学府授传的.NET武学基础系列,秋天勤习之,日复日.月复月,已掌握九九八八一. 然而学无 ...

  3. CodeSmith应用(一)

    这个例子仅是一个简单的应用,在我翻译并学习完CodeSmith的英文帮助文档后,对CodeSmith有了一定的了解,开始着手编写一些CodeSmith应用模板,今天按照最早提到的例子自行编写了一个基于 ...

  4. PowerDesigner最基础的使用方法入门学习2

    from:http://www.cnblogs.com/huangcong/archive/2010/06/14/1757957.html 最近要忙期考,但还是决定每天抽点空来写CodeSmith的系 ...

  5. 图解CodeSmith使用和实用教程一 - 入门和生成MIS项目实体层代码

    CodeSmith,也就是传说中的那个代码生成工具. 下载CodeSmith 6.5,可到我网盘下,链接在底部. 一 安装 1 解压,点击安装: 2 协议: 3 选择目录: 4 一路next完成. 5 ...

  6. 黄聪:CodeSmith和PowerDesigner的使用安装和数据库创建(原创系列教程)

    最近要忙期考,但还是决定每天抽点空来写CodeSmith的系列文章了,在此实在不敢用教程这个词语,毕竟自己对CodeSmith了解的也不是很多,有很多牛人都在博客园发布了不少关于CodeSmith的文 ...

  7. 对使用CodeSmith模板生成NHibernate的代码的分析

    CodeSmith是我们常用的代码生成工具,其跟据不同的模板生成不同代码的方式能大大加快我们的项目开发,减少重复劳动.NHibernate模板就是其常用模板之一.从这里可以下载到最新的模板文件.现在最 ...

  8. codesmith 模板

    近来 两天自身 写了个基本 的ORM框架,特别的Easy,但是没有相应的代码生成工具,于是就很杯具了! 于是乎,花费了一天的时间学习并写了一个CodeSmith可以运用 的模板.在此记录下CodeSm ...

  9. 处女篇:ObjectDataSource+CodeSmith实现基础增删改查功能

    前言: 看别的人博客看多了,自己写博客还是第一次.这里就分享点破东东. SqlDataSource:初学入门者,大伙都会用得比较多,里面一个代码也不用写,排序分页编辑删除插入等功能都给你弄好了.很好用 ...

最新文章

  1. Speedata uhf_7.6.3.jar错误硬代码问题
  2. TCP/IP详解学习笔记-基本概念
  3. java 代码scope注解_Spring学习(15)--- 基于Java类的配置Bean 之 @Bean @Scope 注解
  4. World Token官网钱包收益是骗人的吗?是传销吗?
  5. python-docx 如何获取当前字号_餐饮老字号迈上“云端”
  6. 生态系统长期观测数据产品体系
  7. java的sas数据安全_使用sas中的do循环指定数据信息
  8. 做人不能太心软,这三件事上,越狠心就越受益
  9. 计算机原理华东理工大学期末成绩查询,华东理工大学微机原理历年真题第十一章.ppt...
  10. 论文阅读笔记(五)——FD-MOBILENET
  11. php 邮编 类,邮编查询示例
  12. 有关圣诞节表白的c语言程序,关于圣诞节表白唯美的句子
  13. python时间格式转换为美式日期_python中有关时间日期格式转换问题
  14. 解决idea工具下tomcat中文乱码问题
  15. caniuse-lite is outdated. Please run next command `npm update`
  16. Java爬虫Jsoup爬取必应壁纸
  17. linux灵活提取ip脚本
  18. JS异步:执行原理与回调
  19. 王道操作系统课代表 - 考研计算机 第一章 计算机概述 究极精华总结笔记
  20. 9.7 方向导数与梯度

热门文章

  1. esp8266接收到的数据如何存放到数组中_愉快地学Java语言:第七章 数组
  2. 组件间数据交互||父组件向子组件传值-基本使用|| 父组件向子组件传值-props属性名规则
  3. 组件命名方式||局部组件注册:局部组件只能在注册他的父组件中使用
  4. JdbcTemplate的CRUD操作
  5. Java的知识点28——线程的生命周期
  6. js GB2312和unicode互转
  7. 通过Matlab发送邮件要注意的问题
  8. 计算机原理解读图,详细讲解仪器仪表测试系统,结构原理图拿走不谢
  9. Ubuntu下安装node和npm
  10. 如何使用React Hook