• 蛙蛙推荐:用脚本写一个支持模板的代码生成器


     蛙蛙推荐:用脚本写一个支持模板的代码生成器

    简介:最近很流行代码生成器,大多都是用.NET语言开发的,然后生成.NET语言的代码,我这里演示一个用脚本编写的代码生成器,并且能自定义模板生成任何语言的基于数据库的重复性代码,ASP,VB,C#,PHP都可以,因为生成代码的复杂性,所以要把生成的代码手工复制到IDE工具里面,并不能直接生成.vb,.cs,.asp文件。模板呢,也没有用codesmith那样的模板方式,而是使用了一套更容易理解的xml格式。目前只支持sqlserver,因为我对其它odbc类型和.NET数据库类型的对应还不太了解,因为不是一一对应,所以针对access的代码生成工具不好开发。

     

    简单演示几个功能吧。

     

    一、生成添加数据的代码

    1、先看一下我们要生成的代码

     

    sql="INSERT INTO [Products]([ProductName],[SupplierID],[CategoryID],[QuantityPerUnit],[UnitPrice],[UnitsInStock],[UnitsOnOrder],[ReorderLevel],[Discontinued]) VALUES('"&ProductName&"',"&SupplierID&","&CategoryID&",'"&QuantityPerUnit&"',
    "&UnitPrice&",
    "&UnitsInStock&","&UnitsOnOrder&","&ReorderLevel&","&Discontinued&")"

    这句代码是ASP里很常用的一条添加数据的代码,可以看到,我们需要手工拼接它,并且要注意到字段是数字类型还是字符类型,是字符类型的话还得用单引号把要插入的值括起来。

    2、再来看模板

    <txt ><![CDATA[sql="INSERT INTO [$table](]]></txt>
    <txt cyc="1" arr="arrcol1">
    <t>[$colName]</t>
    <expression="nomax">,</t>
    </txt>
    <txt>) VALUES(</txt>
    <txt cyc="1" arr="arrcol1">
    <expression="isstring"><![CDATA[']]></t>
    <t><![CDATA["&$colName&"]]></t>
    <expression="isstring"><![CDATA[']]></t>
    <expression="nomax">,</t>
    </txt>
    <txt><![CDATA[)"
    ]]></txt>

    解释一下哦$table就相当于当前选定表txt节点的cyc=1表示循环自标签t的内容属性arr="arrcol1"表示子标签的循环是依靠字段列表1,$colName表示字段的名称,expression="nomax"表示循环的时候不是最后一个字段的时候显示。XML的CDATA扩住的部分表示直接输出内容,像单引号,双引号,回车等会直接显示,如果有大块的生成文本,用这个括起来很方便。expression="isstring"用来判断字段类型是否是文本类型,如果当前循环的字段是varchar,char,text等类型就会输出里面的内容。

    当然了,那些标签的含义都是我自己定义并处理的,XML就是元置标语言嘛,我不过利用了一下而已,我的源码是公开的,大家可以加入自己的标签和处理过程。

    3.选择表和字段来生成代码,如下图

    在选择模板下拉框里选择"添加数据的sql语句",数据库里选择northwind数据库,数据表选择products表,字段里选择要插入的字段,然后点击生成代码,再下面的框中就会显示出生成的代码了。

     

    二、看一下如何生成业务实体的模板

    <txt ><![CDATA[//在使用前请再次检查生成代码正确性[这是代码生成器生成的注释,你可以安全的删除它]
    ]]></txt>
    <txt ><![CDATA[public class $tableEntity
    {
    ]]></txt>
    <txt cyc="1" arr="arrcol1">
    <t><![CDATA[    private $col_netype m_$colName;
    ]]></t>
    </txt>
    <txt><![CDATA[
        
    ]]></txt>
    <txt cyc="1" arr="arrcol1">
    <t><![CDATA[public $col_netype $colName
        {
            get { return m_$colName;}
            set { m_$colName = value;}
        }
    ]]></t>
    <expression="nomax"><![CDATA[ ]]></t>
    </txt>
    <txt><![CDATA[}
    ]]></txt>

     

    是不是也很简单呀,不过加了几个标签而已,整个生成过程完全可以自定义。$col_netype表示字段类型对应的.NET类型,这里没有加System.的前缀,因为默认都引入了这个空间,别的标签都解释过了,另外我还打算把asp的adovbs.inc里的类型做个对应,以便生成asp下的业务实体,但那些都是OLE类型和VB常量,我问了一些人,没人给我一个很好的对应列表。

     

    最后生成的代码如下

    //在使用前请再次检查生成代码正确性[这是代码生成器生成的注释,你可以安全的删除它]
    public class ProductsEntity
    {
        
    private String m_ProductName;
        
    private Int32 m_SupplierID;
     
        
    public String ProductName
        
    {
            
    get return m_ProductName;}
            
    set { m_ProductName = value;}
        }

        
    public Int32 SupplierID
        
    {

            
    get return m_SupplierID;}
            
    set { m_SupplierID = value;}
        }

    }

    三、生成赋值语句

    有很多情况下需要给一系列变量赋值,比如下面的ASP代码

    rs("ProductName"= request("ProductName")
    rs(
    "SupplierID"= request("SupplierID")
    rs(
    "CategoryID"= request("CategoryID")
    rs(
    "QuantityPerUnit"= request("QuantityPerUnit")
    rs(
    "UnitPrice"= request("UnitPrice")
    rs.update

    我们的模板更简单

    <txt cyc="1" arr="arrcol1">
    <t><![CDATA[rs("$colName") = request("$colName")
    ]]></t>
    </txt>

    可以稍微改一下就编程.NET里给业务实体赋值的语句了,可以生成类似

    Product.productid = this.productidtextbox.text;这样的语句,字段少的话自己写写就行了,反正有智能感知,但是如果一个表有20多个字段,还是用代码生成器生成一下,粘贴到VS.NET里面算了。

    四、处理存储过程的代码

    比如说处理northwind数据库里的CustOrdersOrders存储过程吧,我们想生成下面的代码

    int ExecuteCustOrdersOrders(String CustomerID)
      
    {

           
    int numAff = -1;
           
    // create the command and the connection
           string connString = "Provider = Sqloledb; Trusted_Connection=yes; Initial Catalog =Northwind; Data Source = 127.0.0.1;";
           SqlConnection conn 
    = new SqlConnection(connString);
           SqlCommand cmd 
    = new SqlCommand("CustOrdersOrders", conn);
           cmd.CommandType 
    = CommandType.StoredProcedure;
     

           cmd.Parameters.Add( 
    new SqlParameter("@CustomerID", System.Data.SqlDbType.NChar, 10));
           cmd.Parameters[
    "@CustomerID"].Direction = ParameterDirection.Input;
           cmd.Parameters[
    "@CustomerID"].Value = CustomerID;
           
    // open the connection, execute the command and close the connection

           conn.Open();
           
    try 
           
    {
                  numAff 
    = cmd.ExecuteNonQuery();
           }

           
    catch (SqlException exc) {      
           }

           
    finally {
                  conn.Close();                
           }
        
           
    return numAff;
      }


    虽然这是个很标准的处理存储过程的代码,但是创建参数,给参数赋值的代码很繁琐,如果你使用sqlhelper类的话还得设置参数缓存什么的,很麻烦,我们可以用下面的模板来帮助我们来生成这些代码,当然了,模板你随便改,因为你用的数据访问组件可能是DAAB,可能是SPL,可能是别的什么的,但肯定有重复繁琐的地方,只要有我们就可以制作模板。

    <txt><![CDATA[int Execute$sp_name(]]></txt>
    <txt cyc="1" arr="arrsp">
    <t><![CDATA[$sp_p_col_netype $sp_p_col_name]]></t>
    <expression="nomax">,</t>
    </txt>
    <txt><![CDATA[)
      {
    ]]></txt>
    <txt><![CDATA[
           int numAff = -1;
           // create the command and the connection
           string connString = "$connstr";
           SqlConnection conn = new SqlConnection(connString);
           SqlCommand cmd = new SqlCommand("$sp_name", conn);
           cmd.CommandType = CommandType.StoredProcedure;
    ]]></txt>
    <txt cyc="1" arr="arrsp">
    <t><![CDATA[
           cmd.Parameters.Add( new SqlParameter("@$sp_p_col_name", $sp_p_col_netdbtype, $sp_p_col_length));
           cmd.Parameters["@$sp_p_col_name"].Direction = $sp_p_col_isout;
    ]]></t>
    <expression="p_noout"><![CDATA[   cmd.Parameters["@$sp_p_col_name"].Value = $sp_p_col_name;]]></t>
    </txt>
    <txt><![CDATA[
           // open the connection, execute the command and close the connection
           conn.Open();
           try 
           {
                  numAff = cmd.ExecuteNonQuery();
           }
           catch (SqlException exc) {      
           }
           finally {
                 conn.Close();                
           }    
           return numAff;
      }
    ]]></txt>

     

    分析一下,$connstr表示默认的数据库链接字符串,arr="arrsp"表示存储过程下拉列表,sp_p_col_netype存储过程参数类型的.NET类型,$sp_p_col_name参数名字,$sp_name存储过程的名字,expression="p_noout"表示当前循环的参数不是输出参数,就是不是output,inputouput或者return$sp_p_col_length表示参数长度,$sp_p_col_isout表示参数的方向,这里只实现inputoutput,如果是inputoutput,return等参数类型,手动弄一下吧,因为系统表里不显示这两种形式,只显示是否是输出参数,就有01

    五、生成界面代码

    生成界面的代码比较复杂,因为界面大部分是html代码,比如说生成一个添加数据的html表单吧,我们得确定每个字段的录入窗口是文本框,下拉框还是选择框,而且如果字段类型是数字类型的话还要生成判断类型的JS函数,如果不会NULL的话还得生成确保输入不为空的JS函数,总的来说,比较麻烦。

    我的思路是,在UITemplate目录下单独再建立一个生成UI的元数据,格式如下

    <database name="Northwind">
    <table name="Products">
    <field validate="noempty" display="input" name="ProductName"></field>
    <field validate="noempty" display="select" name="CategoryID">
    <option selected="true" value="1">1</option>
    <option value="2">2</option>
    </field>
    </table>
    </database>

    每个数据库对应一个database节点,每个表对应一个table节点,每个字段对应一个field节点,validate="noempty",表示生成的输入框不能不输入,你还可以定义成isemail,isstring,>8等格式,呵呵,不过你要自己处理标签哦,display="input",表示用文本框输入,name="ProductName"用来指定输入框的名字,display="select"表示输入界面是一个下拉框,里面的option将完全显示在出来。

    然后代码生成模板如下

    <txt ><![CDATA[
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>代码生成界面</title>
    </head>
    <body>
    <table width="300"  border="1" align="center">
      <form name="form1" method="post" action="">
      <tr>
        <td colspan="2"><div align="center">添加$table</div></td>
      </tr>
    ]]></txt>
    <txt cyc="1" arr="arrcol1">
    <t><![CDATA[
    <tr>
        <td width="71" align="right"><strong>$colName:</strong></td>
        <td width="213">$UI_colName</td>
    </tr>
    ]]></t>
    </txt>
    <txt><![CDATA[
      <tr>
        <td align="right">
          <input type="submit" name="Submit" value="提交">
        </td>
        <td><input type="reset" name="Submit" value="重置"></td>
      </tr>
     </form>
    </table>
    </body>
    </html>
    ]]></txt>

    这里的$UI_colName就是生成的控件,我们选择product表的两个字段来看看生成的代码如何

    生成的代码如下

     

    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=gb2312">
    <title>代码生成界面</title>
    </head>
     
    <body>
    <table width="300"  border="1" align="center">
      
    <form name="form1" method="post" action="">
      
    <tr>
        
    <td colspan="2"><div align="center">添加Products</div></td>
      
    </tr>
    <tr>
        
    <td width="71" align="right"><strong>ProductName:</strong></td>
        
    <td width="213"><input type="text" name="ProductName"></td>
    </tr> 
    <tr>
        
    <td width="71" align="right"><strong>CategoryID:</strong></td>
        
    <td width="213"><select name="CategoryID"><option selected="true" value="1">1</option><option value="2">2</option></select></td>
    </tr>
      
    <tr>
        
    <td align="right">
          
    <input type="submit" name="Submit" value="提交">
        
    </td>
        
    <td><input type="reset" name="Submit" value="重置"></td>
      
    </tr>
      
    </form>
    </table>
    </body>
    </html>

    这不,一个简单的界面已经生成了,如果你会CSS和一些DHTML的话,完全可以生成一个更漂亮的界面,依此类推,数据列表,数据详细信息,数据修改界面也都可以生成。

     

    生成界面的处理有些复杂,各位看不懂,不要紧,基于元数据驱动的UI是个新的课题,慢慢就习惯了可能。

     

    然后,简单介绍一下这个代码生成器的原理,因为我把源码都公开了,所以简单介绍一下原理就行了。打开界面的时候,我在界面上放了一个ado.connection对象,是用<object>标签声明的,然后呢,我用信任链接打开本地的sqlserver数据库,链接到master表上,如果链接失败,就报错,退出,如果连接成功就根据master的信息填充数据库下拉列表,然后选择数据库,再填充字段1,字段2,存储过程下拉框,然后呢,选择要生成代码的模板,字段列表或者存储过程列表的选项,就可以生成代码了。内部运行机理,无非是使用sqlserver的系统表获取选择表或者存储过程的字段或者参数信息,然后根据加载起来的xml模板,交互处理后最终生成需要的代码,但是生成UI的过程需要加载两个XML模板,有些麻烦,别的都很简单了,整个逻辑都在index.htm里,右键用editplus打开就看到源码了,我在大多数地方做了注释,我并没有画整个的处理流程图,因为我不会,在模板标签的指定上也不是很严谨,因为我英文不太懂。

     最后,我这个代码生成器的安装包是用winrar做的自解压exe程序,不是病毒哦,里面有我写的一个部署文件的.vbs文件,它的功能是在桌面上生成一个index.htm的快捷方式,所有文件默认都安装到C:\wawa\wawacodepro目录下,而且会在桌面上生成一个快捷方式,直接就可以用,如果你选择了其它的安装目录,那么更新一下桌面快捷方式的指向就行了,不过最好不要改默认安装路径,这样直接就可以用了。

     我认为大规模的代码生成,比如MDA等现在不容易实现,而小范围的代码生成却可以很大的减少重复劳动,提高效率。 

    知道了原理后,大家可以开发一些生成各种代码的模板,如果你做了不错的模板请联系我哦,呵呵。

    下载地址https://files.cnblogs.com/onlytiancai/wawacodepro.rar

  • 相关阅读:
    Linux OTG当串口、网口、U盘
    Linux 双网卡双网段通信
    Buildroot Savedefconfig
    OTG作为大容量设备
    EntityFramework Core问题处理集锦(一)
    EntityFramework Core数据查询
    ASP.NET Core MVC请求超时设置解决方案
    EntityFramework Core迁移时出现数据库已存在对象问题解决方案
    EntityFramework Core映射关系详解
    探讨SQL Server并发处理存在就更新七种解决方案
  • 原文地址:https://www.cnblogs.com/onlytiancai/p/224005.html
Copyright © 2020-2023  润新知