架构深渊

慢慢走进程序的深渊……关注领域驱动设计、测试驱动开发、设计模式、企业应用架构模式……积累技术细节,以设计架构为宗。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Nettiers整理出来的codesmith模板编写要点[转]

Posted on 2009-06-19 13:04  chen eric  阅读(722)  评论(0编辑  收藏  举报

 

//模板的基础知识

//任何模板都需要的第一句,用来指定模板编辑语言是什么,目标语言是什么:
<%@ CodeTemplate Language="C#" TargetLanguage="T-SQL" Description="Generates a update stored procedure." %>

//接下来写模板需要从外界引入的参数
<%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" Category="Context" Description="Database" %>

//在模板里面用到了codesmith的函数和方法,需要引入对应的包,一般是
<%@ Assembly Name="SchemaExplorer" %>
<%@ Import Namespace="SchemaExplorer" %>

我理解assembly 是引入dll,import 是引入dll里面的命名空间,这些dll有的是codesmith自己带的,对于vs.net提供的dll,都可以引入使用。

//所有codesmith函数都在script标签里面定义,包括变量
<script runat="template">
private string _outputDirectory = String.Empty;

</script>

调用用
<% %> 括起来,一般有一个主函数来执行整个模板的函数
<%
this.Go();
%>

将生成的变量插入到模板的任何需要动态生成的地方,直接用asp的写法就可以了,例如
namespace <%=DALNameSpace%>.SqlClient



//一般模板的函数和用法


/// <summary>
/// 拷贝指定文件
/// </summary>
public void SafeCopyFile(string path, string destination)
{
FileInfo file1 
= new FileInfo(path);
file1.CopyTo(destination, 
true);
}

/// <summary>
/// 创建指定目录
/// </summary>
public void SafeCreateDirectory(string path)
{
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
}


/// <summary>
/// 根据指定模板生成指定文件
/// </summary>
public void RenderToFile(string templateName, string path, bool overwrite)
{
this._CurrentFileName = path;
this.GetTemplate(templateName).RenderToFile(path, overwrite);
this._counter++;
}


/// <summary>
/// 打开文件目录,[Editor]标签表示调用指定的编辑器;category表示参数所属目录;Descript表示对参数的描述;defaultvalue表示缺省值
CodeTemplateProperty表示该参数是可选还是必须的,CodeTemplatePropertyOption.Optional是可选,CodeTemplatePropertyOption.Required是必


/// </summary>
private string _outputDirectory = String.Empty;
[Editor(
typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))] 
[CodeTemplateProperty(CodeTemplatePropertyOption.Optional)]
[Category(
"General")]
[Description(
"The directory to output the results to.")]
[DefaultValue(
"")]
public string OutputDirectory 

get
{
if (_outputDirectory.Length == 0)
{
return @"c:\NetTiers\Output");
}
else
{
return _outputDirectory;
}
}
set
{
if (value.EndsWith("\\")) value = value.Substring(0, value.Length - 1);
_outputDirectory 
= value;

}


//获取当前打开模板所在路径
this.CodeTemplateInfo.DirectoryName


//对于模板,当前打开的模板可以用codeTemplateInfo访问,其他的子模板需要先根据文件名和路径载入,然后编辑模板,最后赋予参数,生成文件。

//设定模板路径
private string[] _templatesFileNames = new string[] {
"vsnet2003.project.cst",
"vsnet2005.project.cst",
"vsnet2003.solution.cst",
"vsnet2005.solution.cst",
"ASP.Net\\2.0\\Entty_aspx_resx.cst"
};

//设定编辑好的子模板保存的hashtable,在hashtable里面,key是文件名,所以全套模板不能有重复的文件名
// Compile and load all them in a collection
private System.Collections.Hashtable _CodeTemplates = new System.Collections.Hashtable();

//载入模板
// load all the templates and put them into an hashtable
public void LoadTemplates()

foreach(string _templatesFileName in _templatesFileNames)
{
string key = System.IO.Path.GetFileName(_templatesFileName);

if (_CodeTemplates.Contains(key))
{
continue;
}

_CodeTemplates.Add(key, 
this.CompileTemplate(this.CodeTemplateInfo.DirectoryName + _templatesFileName));

// Set the properties that all the commonsqlcode inherited templates should set
// TODO : use reflection to check that the templates inherits from commonsql
try
{
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"EntityFormat", EntityFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"CollectionFormat"

CollectionFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"ProviderFormat", ProviderFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"InterfaceFormat", InterfaceFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"BaseClassFormat", BaseClassFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"EnumFormat", EnumFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"ManyToManyFormat"

ManyToManyFormat);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"AliasFilePath", AliasFilePath);
((CodeSmith.Engine.CodeTemplate)_CodeTemplates[key]).SetProperty(
"StrippedTablePrefixes"

StrippedTablePrefixes);
}
catch(Exception) {}
}
}


//载入的时候都需要编译模板
public CodeTemplate CompileTemplate(string templateName)
{
this._CurrentFileName = templateName;

CodeTemplateCompiler compiler 
= new CodeTemplateCompiler(templateName);
compiler.Compile();

if (compiler.Errors.Count == 0)
{
return compiler.CreateInstance();
}
else
{
for (int i = 0; i < compiler.Errors.Count; i++)
{
Response.WriteLine(compiler.Errors[i].ToString());
}
return null;
}
}

//获取模板
public CodeTemplate GetTemplate(string templateType)
{
return (CodeSmith.Engine.CodeTemplate)_CodeTemplates[templateType];
}


//给模板赋值
this.GetTemplate("EntityProviderBase.cst").SetProperty("SourceTable", SourceTable);



//数据库属性
<%@ Property Name="SourceDatabase" Type="SchemaExplorer.DatabaseSchema" Optional="False" Category="DataSource" 

Description
="Database that the stored procedures should be based on." %>


//遍历数据库里面的所有数据表
private TableSchemaCollection _sourceTables;
private ViewSchemaCollection _sourceViews;
for (int i=0; i < SourceDatabase.Tables.Count; i++)
{
_sourceTables.Add(SourceDatabase.Tables[i]);
}

//遍历数据库里面的所有视图
for (int i=0; i < SourceDatabase.Views.Count; i++)
{
_sourceViews.Add(SourceDatabase.Views[i]);
}

//获取表格名
SourceTables[i].Name

//遍历表的结构
for (int i=0; i< SourceTable.Columns.Count; i++) {
Response.Write(
"\""+ SourceTable.Columns[i].Name + "\""); }

//指定打开哪个或者哪几个表
[Category("DataSource")]
[Description(
"The tables to generate.")]
[CodeTemplateProperty(CodeTemplatePropertyOption.Optional)]
public TableSchemaCollection SourceTables
{
get
{
if (this._sourceTables != null && this._sourceTables.Count > 0 )
return this._sourceTables;
else
return null;
}
set
{
this._sourceTables = value;
}
}


//关于遍历文件夹和拷贝文件夹里面所有文件是我自己写的,在nettiers里面没有用例:
//拷贝目录
public void CopyDirectory(string path)
{
SafeCreateDirectory(OutputDirectory
+path);

DirectoryInfo dir 
= new DirectoryInfo(this.CodeTemplateInfo.DirectoryName+path);
FileInfo[] fileList 
= dir.GetFiles();
foreach (FileInfo sourceFile in fileList) 

sourceFile.CopyTo(OutputDirectory 
+ path+"\\"+sourceFile.Name, true);
Response.WriteLine(
"Copy file: " + sourceFile.Name);
}
}

//遍历文件夹:先打开目录,然后载入目录下的文件,这个操作完全是用c#代码来写的,更多功能可以参考msdn
DirectoryInfo dir = new DirectoryInfo(this.CodeTemplateInfo.DirectoryName+path);
FileInfo[] fileList 
= dir.GetFiles();
foreach (FileInfo sourceFile in fileList) 

sourceFile.CopyTo(OutputDirectory 
+ path+"\\"+sourceFile.Name, true);
Response.WriteLine(
"Copy file: " + sourceFile.Name);

}

//完整例子请参阅nettiers,这是一个相当不错的完整的例子,美中不足是没有web层代码模板。