码迷,mamicode.com
首页 > 其他好文 > 详细

使用模板引擎(Nvelocity)写代码生成器

时间:2015-12-15 12:10:35      阅读:190      评论:0      收藏:0      [点我收藏+]

标签:

  之前做了一个项目,由于数据库表比较多,每次都手写model,还有数据库操作之类的东西,感觉浪费时间,也没技术含量,还容易出错,最主要的原因还是懒,不想翻来覆去的写这种代码,于是想到要用代码生成器直接生成,在网上找到很多,但是生成的代码要么看着不安逸,毕竟每个人的风格不同,要么就是生成很多自己根本不需要的垃圾代码,正好最近闲来无事,决定自己动手写一个。

  一开始我是想到使用stringbuilder拼接字符串来实现,但是字符串拼接起来相当麻烦,代码量也很多,看起乱糟糟的很不舒服,还有就是得注意格式,不然生成出来的代码一团乱,于是看到园子里有大神用模板引擎实现过,但是看不到源码,用一段时间了还要付费,但是也提供了我一种思路,模板引擎可以实现。搜了很多关于模板引擎的资料,但是大多都是11年以前的,由于本人13年才正式踏入程序员行列,对于这项技术是不是过时了,我也不是很清楚,估计有了razor视图引擎,Nvelocity就显得有点不足了。这有篇介绍razor视图引擎做模板的例子:http://www.cnblogs.com/lxfqlcz/archive/2012/02/22/2363504.html,不过可以肯定的是,使用它比拼接字符串有很多好处,比如:开发效率高;代码不混乱,至少自己看着满意;不用注意格式,比如需要几个空格之类的;但是也有缺点,比如关键字不高亮;没有智能提示;也没法格式化,手动格式话了之后生成的代码就不是自己想要的格式了。所以一旦模板中有点小错误,很难找出来。

一、模板引擎之Nvelocity简介

  网上关于这项技术的资料很多,下面罗列一些,就不介绍了。

    http://www.cnblogs.com/hxling/archive/2011/10/23/2221918.html

    http://www.cnblogs.com/cnfblog/archive/2010/10/18/1853987.html

    http://www.cnblogs.com/waynechan/p/3489136.html

二、代码生成器的前期工作

  1.查询表结构

    1.1 方式1

SELECT  col.name AS 列名 ,
        typ.name AS 数据类型 ,
        col.max_length AS 占用字节数 ,
        col.is_nullable AS 是否允许非空 ,
        col.is_identity AS 是否自增 ,
        CASE WHEN EXISTS ( SELECT   1
                           FROM     sys.indexes idx
                                    JOIN sys.index_columns idxCol ON ( idx.object_id = idxCol.object_id )
                           WHERE    idx.object_id = col.object_id
                                    AND idxCol.index_column_id = col.column_id
                                    AND idx.is_primary_key = 1 ) THEN 1
             ELSE 0
        END AS 是否是主键
FROM    sys.columns col
        LEFT JOIN sys.types typ ON ( col.system_type_id = typ.system_type_id
                                     AND col.user_type_id = typ.user_type_id
                                   )
WHERE   col.object_id = ( SELECT    object_id
                          FROM      sys.tables
                          WHERE     name = ‘SYS_ParameterGroup‘
                        )

效果:
GroupID		int		4	0	1	1
GroupName	varchar		200	1	0	0

     1.2 方式2

SELECT  a.colorder 字段序号 ,
        a.name 字段名 ,
        ( CASE WHEN COLUMNPROPERTY(a.id, a.name, ‘IsIdentity‘) = 1 THEN ‘1‘
               ELSE ‘0‘
          END ) 标识 ,
        ( CASE WHEN ( SELECT    COUNT(*)
                      FROM      sysobjects
                      WHERE     ( name IN (
                                  SELECT    name
                                  FROM      sysindexes
                                  WHERE     ( id = a.id )
                                            AND ( indid IN (
                                                  SELECT    indid
                                                  FROM      sysindexkeys
                                                  WHERE     ( id = a.id )
                                                            AND ( colid IN (
                                                              SELECT
                                                              colid
                                                              FROM
                                                              syscolumns
                                                              WHERE
                                                              ( id = a.id )
                                                              AND ( name = a.name ) ) ) ) ) ) )
                                AND ( xtype = ‘PK‘ )
                    ) > 0 THEN ‘1‘
               ELSE ‘0‘
          END ) 主键 ,
        b.name 类型 ,
        a.length 占用字节数 ,
        COLUMNPROPERTY(a.id, a.name, ‘PRECISION‘) AS 长度 ,
        ISNULL(COLUMNPROPERTY(a.id, a.name, ‘Scale‘), 0) AS 小数位数 ,
        ( CASE WHEN a.isnullable = 1 THEN ‘1‘
               ELSE ‘0‘
          END ) 允许空 ,
        ISNULL(g.[value], ‘ ‘) AS 说明
FROM    syscolumns a
        LEFT JOIN systypes b ON a.xtype = b.xusertype
        INNER JOIN sysobjects d ON a.id = d.id
                                   AND d.xtype = ‘U‘
                                   AND d.name <> ‘dtproperties‘
        LEFT JOIN syscomments e ON a.cdefault = e.id
        LEFT JOIN sys.extended_properties g ON a.id = g.major_id
                                               AND a.colid = g.minor_id
        LEFT JOIN sys.extended_properties f ON d.id = f.class
                                               AND f.minor_id = 0
WHERE   b.name IS NOT NULL
        AND d.NAME = ‘USER_User‘ORDER BY a.id ,
        a.colorder

效果:
技术分享

  目前还没搞明白sys.columns与syscolumns之间的区别,反正两者都能实现。查了MSDN貌似说的两者都差不多。

三、写一个Nvelocity帮助类,以方便我们使用Nvelocity,同时减少代码量,这里引用的Nvelocity当然需要先下载准备好,然后添加引用

  1 using System;
  2 using System;
  3 using System.Web;
  4 using System.IO;
  5 using NVelocity;
  6 using NVelocity.App;
  7 using NVelocity.Context;
  8 using NVelocity.Runtime;
  9 using Commons.Collections;
 10 using System.Windows.Forms;
 11 
 12 
 13 namespace NVelocityDemo
 14 {
 15     /// <summary>
 16     /// NVelocity模板工具类 NVelocityHelper
 17     /// </summary>
 18     public class NVelocityHelper
 19     {
 20         private VelocityEngine velocity = null;
 21         private IContext context = null;
 22         private string templateDir = "/Template";
 23 
 24         /// <summary>
 25         /// 构造函数
 26         /// </summary>
 27         /// <param name="ps_TemplateDir">模板文件夹路径</param>
 28         public NVelocityHelper(string ps_TemplateDir)
 29         {
 30             templateDir = ps_TemplateDir;
 31             Init();
 32         }
 33 
 34         /// <summary>
 35         /// 无参数构造函数
 36         /// </summary>
 37         public NVelocityHelper() { Init(); }
 38 
 39         /// <summary>
 40         /// 初始化NVelocity模块 
 41         /// create by liubiqu@hotmail.com 2010-04-14
 42         /// </summary>
 43         private void Init()
 44         {
 45             //创建VelocityEngine实例对象
 46             velocity = new VelocityEngine();
 47 
 48             //使用设置初始化VelocityEngine
 49             ExtendedProperties props = new ExtendedProperties();
 50             props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
 51             props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, Application.StartupPath + templateDir);
 52             props.AddProperty(RuntimeConstants.INPUT_ENCODING, "utf-8");
 53             props.AddProperty(RuntimeConstants.OUTPUT_ENCODING, "utf-8");
 54             velocity.Init(props);
 55 
 56             //为模板变量赋值
 57             context = new VelocityContext();
 58         }
 59 
 60         /// <summary>
 61         /// 给模板变量赋值
 62         /// </summary>
 63         /// <param name="key">模板变量</param>
 64         /// <param name="value">模板变量值</param>
 65         public void Add(string key, object value)
 66         {
 67             if (context == null)
 68                 context = new VelocityContext();
 69             context.Put(key, value);
 70         }
 71 
 72         /// <summary>
 73         /// 通过获得模板文件生成结果字符串
 74         /// </summary>
 75         /// <param name="ps_TemplateFileName">模板文件名,为从模板目录开始的完整路径。即相对路径。如cms/news_view.htm</param>
 76         public string GetStringFromVm(string ps_TemplateFileName)
 77         {
 78             //从文件中读取模板
 79             Template template = velocity.GetTemplate(ps_TemplateFileName);
 80             //合并模板
 81             StringWriter writer = new StringWriter();
 82             template.Merge(context, writer);
 83             //输出
 84             string retValue = writer.GetStringBuilder().ToString();
 85             writer.Flush();
 86             writer.Close();
 87             writer.Dispose();
 88             return retValue;
 89         }
 90 
 91         /// <summary>
 92         /// 生成字符串内容
 93         /// </summary>
 94         /// <param name="stringExpression">要解析的字符串数据</param>
 95         /// <param name="logTag">Log标识</param>
 96         /// <returns></returns>
 97         public string GetStringFromSource(string ps_SourceStr)
 98         {
 99             StringWriter writer = new StringWriter();
100             velocity.Evaluate(context, writer, "log", ps_SourceStr);
101             //输出
102             string retValue = writer.GetStringBuilder().ToString();
103             writer.Flush();
104             writer.Close();
105             writer.Dispose();
106             return retValue;
107         }
108 
109     }
110 
111 }

四、编写模板,这里来个简单的,生成实体类的模板,模板的后缀名为vm,必须设置文件的"复制到输出目录"属性,不然运行时会提示找不到模板文件。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace $namespaceName
{
    [Serializable]
    public class $tableName
    {
##自动属性方式 #if($isAutoProperty) #foreach($TableInfo in $listTableStructInfo) /// <summary> /// $TableInfo.Description /// </summary> public ${commonObj.GetType($TableInfo.Type)} ${commonObj.GetFirstUpperOrLower($TableInfo.Row,true)}{ get; set; } #end #else #foreach($TableInfo in $listTableStructInfo) private ${commonObj.GetType($TableInfo.Type)} _${commonObj.GetFirstUpperOrLower($TableInfo.Row,false)}; /// <summary> /// $TableInfo.Description /// </summary> public ${commonObj.GetType($TableInfo.Type)} ${commonObj.GetFirstUpperOrLower($TableInfo.Row,true)} { get { return _${commonObj.GetFirstUpperOrLower($TableInfo.Row,false)}; } set { _${commonObj.GetFirstUpperOrLower($TableInfo.Row,false)} = value; } } #end #end } }

 五、调用模板生成文件

 1 private void GetModel(ProgressBar bar, NVelocityHelper velocity, Common common)
 2         {
 3             int i = 0; bar.Maximum = lsTable.Count;
 4             foreach (string table in lsTable)
 5             {
 6                 //表结构
 7                 List<TableInfo> listTableStructInfo = Common.GetTableStruct(table);
 8                 if (listTableStructInfo.Count <= 0)
 9                 {
10                     continue;
11                 }
12                 bar.Value = ++i;
13                 //创建文件
14                 string newPath = Common.CreateFile(Common.CreateFolder(rootPath, nameSpaceModel.NamespaceEntity), common.GetFirstUpperOrLower(table, true) + ".cs");
15                 //命名空间名称
16                 velocity.Add("namespaceName", nameSpaceModel.NamespaceEntity);
17                 //表名
18                 velocity.Add("tableName", table);
19                 //表结构
20                 velocity.Add("listTableStructInfo", listTableStructInfo);
21                 //调用方法需要的对象
22                 velocity.Add("commonObj", common);
23                 //生成自动属性
24                 if (nameSpaceModel.IsAutoProperty)
25                 {
26                     velocity.Add("isAutoProperty", true);
27                 }
28                 string text = velocity.GetStringFromVm("model.vm");
29                 File.AppendAllText(newPath, text);
30             }
31             bar.Value = 0;
32         }

生成实体类的效果如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Models
{
    [Serializable]
    public class USER_User
    {
        /// <summary>
        /// 用户ID
        /// </summary>
        public string UserID{ get; set; }

        /// <summary>
        /// 用户名
        /// </summary>
        public string Name{ get; set; }

        /// <summary>
        /// 证件类型ID,对应SYS_CardType表
        /// </summary>
        public int CardTypeID{ get; set; }

        /// <summary>
        /// 证件号码
        /// </summary>
        public string CardNum{ get; set; }

    }
}

 完整代码下载地址:demo下载

 

    

 

使用模板引擎(Nvelocity)写代码生成器

标签:

原文地址:http://www.cnblogs.com/ginb/p/5044528.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!