CodeSmith学习笔记

最近因项目需要学习了一下CodeSmith。CodeSmith是一个基于模板的代码生成工具,可以用它来快速生成代码,减少项目编码中的重复劳动。
我们可以在CodeSmith中制定模板(当然这些模板是可以重复使用的),然后输入一些参数,最后生成所需的代码脚本。这就是CodeSmith大体的工作流程啦。
我认为CodeSmith最核心的思想是将一个代码文件中的内容分解成几个部分,即:
固定不变的内容(Content that will never change);
可自动产生的内容(Content that can be automatically generated);
可让用户指定的内容(Content that you will prompt the user for)。


固定不变的内容主要是由一些固定格式的声明、定义和特定的方法调用,这些内容构成我们模板的大体结构。
可自动产生的内容主要是一些在代码生成时能自动产生的信息,如代码生成日期,这些信息我么可以通过调用方法来获得。
可让用户指定的内容则是由模板得到最终代码所需的一些参数,不同的参数导致由同一模板生成不同的实际代码,是从抽象到具体的桥梁。
下面一个简单的例子说明了以上三点。

<%--  
Name: HelloWorldTemplate
Author: Aixe
Description: The 
is  a simple template to help learn CodeSmith.
--%>
<% @ CodeTemplate Language = " C# "  TargetLanguage = " C# "
    Description
= " A simple template for Hello World program. "   %>
<% @ Property Name = " NamespaceName "  Type = " System.String "  Default = " HelloWorld "
    Optional
= " False "  Category = " Context "  Description = " A name for your namespace. "   %>
<% @ Property Name = " ClassName "  Type = " System.String "  Default = " Program "
    Optional
= " False "  Category = " Context "  Description = " A name for your class. "   %>
<% @ Property Name = " ClassAccessibility "  Type = " AccessibilityEnum "
    Optional
= " True "  Category = " Context "  Description = " The accessibility of your class. "   %>
<% @ Property Name = " Author "  Type = " System.String "
    Optional
= " False "  Category = " Customized "  Description = " Your name here. "   %>
<% @ Property Name = " Words "  Type = " System.String "  Default = " Hello World! "
    Optional
= " False "  Category = " Content "  Description = " Words to say. "   %>
<% @ Assembly Name = " System.Data "   %>
<% @ Import Namespace = " System "   %>
//  This code is writen by: <%= Author %>
//  Create at: <%= DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") %>
using  System;
namespace   <%=  NamespaceName  %>
{
    
<%=  GetAccessibility()  %>   class   <%=  ClassName  %>
    {
        
static   void  Main( string [] args)
        {
            Console.WriteLine(
" <%= Words %> " );
            Greeting(
" <%= Author %> " );
        }
        
        
static   void  Greeting( string  name)
        {
            Console.WriteLine(
string .Format( " Hello, {0} " , name));
        }
    }
}
< script runat = " template " >
public   enum  AccessibilityEnum
{
    Public,
    Protected,
    Private,
}
public   string  GetAccessibility()
{
    
switch (ClassAccessibility)
    {
        
case  AccessibilityEnum.Public:  return   " public " ;
        
case  AccessibilityEnum.Protected:  return   " protected " ;
        
case  AccessibilityEnum.Private:  return   " private " ;
        
default return   string .Empty;
    }
}
</ script >

整个模板大致分为3个部分:模板和属性声明,模板主体和脚本。
每个模板前面都有一个声明语句,标明模板使用的语言和目标语言:
<% @ CodeTemplate Language = " C# "  TargetLanguage = " C# "
    Description
= " A simple template for Hello World program. "   %>

接下来声明了模板中用到的几个属性,分别是命名空间的名字(NamespaceName),类名(ClassName),类的访问类型(ClassAccessibility),这是一个枚举类型,在后面的脚本中有定义,作者(Author)和一句信息(Words)。这些信息都由用户自己来输入的。这里的一些属性给出了默认值。
<% @ Property Name = " NamespaceName "  Type = " System.String "  Default = " HelloWorld "
    Optional
= " False "  Category = " Context "  Description = " A name for your namespace. "   %>
<% @ Property Name = " ClassName "  Type = " System.String "  Default = " Program "
    Optional
= " False "  Category = " Context "  Description = " A name for your class. "   %>
<% @ Property Name = " ClassAccessibility "  Type = " AccessibilityEnum "
    Optional
= " True "  Category = " Context "  Description = " The accessibility of your class. "   %>
<% @ Property Name = " Author "  Type = " System.String "
    Optional
= " False "  Category = " Customized "  Description = " Your name here. "   %>
<% @ Property Name = " Words "  Type = " System.String "  Default = " Hello World! "
    Optional
= " False "  Category = " Content "  Description = " Words to say. "   %>

接下来定义代码的模板主体,这里的内容大多是不变的,需要变动的地方就通过嵌入一段代码来得到动态的内容。
其中namespace的名字使用的是NamespaceName这个属性的值,类名用的是ClassName的值,通过调用GetAccessibility()方法得到类的访问属性。这些属性值是用户来指定的。不难发现,其写法很像ASP.NET中的数据绑定。
注释中的Create at一句则是通过调用System.DateTime.Now来获得代码创建的时间,属于自动生成的部分。
//  This code is writen by: <%= Author %>
//  Create at: <%= DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss") %>
using  System;
namespace   <%=  NamespaceName  %>
{
    
<%=  GetAccessibility()  %>   class   <%=  ClassName  %>
    {
        
static   void  Main( string [] args)
        {
            Console.WriteLine(
" <%= Words %> " );
            Greeting(
" <%= Author %> " );
        }
        
        
static   void  Greeting( string  name)
        {
            Console.WriteLine(
string .Format( " Hello, {0} " , name));
        }
    }
}

我们在定义ClassAccessibility这个属性时,使用了自定义的枚举类型AccessibilityEnum,因此还要在脚本中声明之。另外由于public, protected和,private是C#里的关键字,所以枚举里面的首字母P不能小写。为了根据ClassAccessibility属性的值获得类的访问属性,还需编写GetAccessibility()方法。
< script runat = " template " >
public   enum  AccessibilityEnum
{
    Public,
    Protected,
    Private,
}
public   string  GetAccessibility()
{
    
switch (ClassAccessibility)
    {
        
case  AccessibilityEnum.Public:  return   " public " ;
        
case  AccessibilityEnum.Protected:  return   " protected " ;
        
case  AccessibilityEnum.Private:  return   " private " ;
        
default return   string .Empty;
    }
}
</ script >

完成以上步骤后,一个简单的模板就做好了。编译之后,可在属性面板里看到我们自定义的属性在这里被列了出来:

输入Author属性再运行,就可得到我们需要的代码了。
//  This code is writen by: Aixe
//  Create at: 2009-08-02 10:52:24
using  System;
namespace  HelloWorld
{
    
public   class  Program
    {
        
static   void  Main( string [] args)
        {
            Console.WriteLine(
" Hello World! " );
            Greeting(
" Aixe " );
        }
        
        
static   void  Greeting( string  name)
        {
            Console.WriteLine(
string .Format( " Hello, {0} " , name));
        }
    }
}

更改属性之后可以生成不同的代码。
可以看出,写CodeSmith模板和写ASP.NET很类似,熟悉的同学应该能很快上手。以上就是对CodeSmith的一次小小的体验,当然CodeSmith还有很多强大的功能和用法,CodeSmith本身也为我们提供许多很有用的模板供我们学习和使用,具体可以参考CodeSmith的帮助文档或网上的一些资料。

你可能感兴趣的:(code)