zoukankan      html  css  js  c++  java
  • (转)简单代码生成器原理剖析

    原文地址:http://www.cnblogs.com/OceanEyes/archive/2012/02/16/CodeGenerator.html

    上篇文章(深入浅出三层架构)分析了简单三层架构的实现。包括Model,DAL(数据访问层),BLL(业务逻辑层)的实现。

    实际开发中,由于重复代码的操作,会花费大量时间,如果以代码生成器来自动生成三层架构代码,即节省精力,又可以节省大量的时间来做其他业务逻辑的代码,提高开发效率。

    常用的代码生成器有:动软,CodeSmith 等。

    简单代码生成器的基本功能描述:

    一键生成Model,DAL,BLL,包括对应数据库中表的Model的自动生成,包括生成属性、添加、修改、删除、查询。

    界面展示:

    生成器开发技术要点:

    1. 查询系统视图:INFORMATION_SCHEMA.TABLES、 INFORMATION_SCHEMA.COLUMNS  可以获得数据库中表、列的相关信息。
    2. 字符串的拼接:StringBuilder的使用,其AppendLine()会自动换行。
    3. 将字符串写入文本文件:File.WriteAllText()
    4. 为了降低开发难度,先假设条件多一些,如表的主键都为Id,且自动增长,之后再逐步完善

    关键代码:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.Data.SqlClient;
    using System.IO;

    namespace CodeGenerator
    {
    public partial class Form1 : Form
    {
    public Form1()
    {
    InitializeComponent();
    }
    /// <summary>
    /// 执行ExecuteDataTable(),得到DataTable
    /// </summary>
    /// <param name="cmdText"></param>
    /// <param name="parameters"></param>
    /// <returns></returns>
    public DataTable ExecuteDataTable(string cmdText,
    params SqlParameter[] parameters)
    {
    using (SqlConnection conn=new SqlConnection(txtConnStr.Text))
    {
    conn.Open();
    using(SqlCommand cmd=conn.CreateCommand())
    {
    cmd.CommandText = cmdText;
    cmd.Parameters.AddRange(parameters);
    using (SqlDataAdapter adapter=new SqlDataAdapter (cmd))
    {
    DataTable dt = new DataTable();
    adapter.Fill(dt);
    return dt;
    }
    }
    }

    }

    private void Form1_Load(object sender, EventArgs e)
    {
    txtConnStr.Text = @"Data Source=EYES\SQLEXPRESS;Initial Catalog=SanCeng;Integrated Security=True";
    }

    private void btnConnStr_Click(object sender, EventArgs e)
    {

    //清空
    clbTables.Items.Clear();
    //查询系统试图
    string sql = "select * from INFORMATION_SCHEMA.TABLES";
    DataTable dt = ExecuteDataTable(sql);
    //根据系统视图取得TABLE_NAME
    foreach (DataRow row in dt.Rows)
    {
    string tablename = Convert.ToString(row["TABLE_NAME"]);
    clbTables.Items.Add(tablename);
    }

    }

    private void btnGo_Click(object sender, EventArgs e)
    {
    //连接字符串
    //方法AppendLine()追加字符串且自动执行换行

    foreach (string tableName in clbTables.CheckedItems)
    {
    string sql = "select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME=@TABLE_NAME ";
    DataTable dt = ExecuteDataTable(sql,new SqlParameter("TABLE_NAME",tableName));

    #region 生成Model
    CreatModel(tableName, dt);
    #endregion

    #region 生成DAL


    CreatDAL(tableName, dt);
    #endregion
    #region 生成BLL
    CreatBLL(tableName, dt);
    #endregion
    }
    }

    private static void CreatDAL(string tableName, DataTable dt)
    {
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("using System;");
    sb.AppendLine("using System.Collections.Generic;");
    sb.AppendLine("using System.Linq;");
    sb.AppendLine("using System.Text;");
    sb.AppendLine("using 三层架构Demo.Model;");
    sb.AppendLine("using System.Data.SqlClient;");
    sb.AppendLine("using System.Data;");
    sb.AppendLine("namespace 三层架构Demo.DAL");
    sb.AppendLine("{");
    sb.AppendLine("class " + tableName + "DAL");
    sb.AppendLine("{");
    //去掉Id
    sb.AppendLine(" public int Addnew(" + tableName + " model)");
    sb.AppendLine("{");
    List<String> cols = new List<string>();
    List<String> parameters = new List<string>();
    foreach (DataRow row in dt.Rows)
    {
    string col = Convert.ToString(row["COLUMN_NAME"]);
    string parameter = "";
    if (col.ToLower()!="id")
    {
    parameter= "@" + Convert.ToString(row["COLUMN_NAME"]);
    cols.Add(col);
    parameters.Add(parameter);
    }
    //parameters.Add(parameter)放外面加上一个NULL,所以会多出一个逗号
    // parameters.Add(parameter);

    }

    sb.AppendLine("string sql = \"insert into " + tableName + "(" + String.Join(",", cols) + ") output inserted.Id values(" + String.Join(",", parameters) + ")\";");
    sb.AppendLine("object obj= SQLHelper.ExecuteScalar(sql");

    foreach (DataRow row in dt.Rows)
    {
    string col = Convert.ToString(row["COLUMN_NAME"]);
    if (col.ToLower() != "id")
    {
    sb.AppendLine(",new SqlParameter(\"" + col + "\",model." + col + ")");
    }

    }
    sb.AppendLine(");");
    sb.AppendLine("return Convert.ToInt32(obj);");
    sb.AppendLine("}");
    //Delete方法

    sb.AppendLine(" public int Delete(int id)");
    sb.AppendLine("{");
    sb.AppendLine(" string sql = \"delete from " + tableName + " where Id=@Id\";");
    sb.AppendLine("return SQLHelper.ExecuteNonQuery(sql,new SqlParameter(\"Id\",id));");
    sb.AppendLine("}");

    //Update方法
    sb.AppendLine("public int Update("+tableName+" model)");
    sb.AppendLine("{");
    string[] uParams1=(from col in cols select col+"=@"+col).ToArray();

    sb.AppendLine(" string sql = \"update "+tableName+" set "+String.Join(",",uParams1)+" where Id=@Id\";");

    string[] uParams2 = (from col in cols select "new SqlParameter(\"" + col + "\",model." + col + ")").ToArray();
    sb.AppendLine(" return SQLHelper.ExecuteNonQuery(sql, " + String.Join(",", uParams2) + " ,new SqlParameter(\"Id\",model.Id));");
    sb.AppendLine("}");

    //GetId方法
    sb.AppendLine(" public "+tableName+" Get(int id)");
    sb.AppendLine("{");
    sb.AppendLine("string sql=\"select * from "+tableName+" where Id=@Id\";");
    sb.AppendLine(" DataTable dt=SQLHelper.ExecuteDataTable(sql,new SqlParameter(\"Id\",id));");
    sb.AppendLine("if (dt.Rows.Count<=0)");
    sb.AppendLine("{");
    sb.AppendLine(" return null;");
    sb.AppendLine("}");
    sb.AppendLine(" else if (dt.Rows.Count==1)");
    sb.AppendLine("{");
    sb.AppendLine(""+tableName+" model1 = new "+tableName+"();");
    foreach (DataRow row in dt.Rows)
    {
    string col = Convert.ToString(row["COLUMN_NAME"]);
    string dataType = Convert.ToString(row["data_TYPe"]);
    sb.AppendLine("model1." + col + " = Convert." + Get(GetType(dataType).ToString()) + "(dt.Rows[0][\"" + col + "\"]);");

    }
    sb.AppendLine("return model1;");
    sb.AppendLine("}");
    sb.AppendLine("else");
    sb.AppendLine("{");
    sb.AppendLine(" throw new Exception(\"数据库中有两条及以上重复数据\");");
    sb.AppendLine("}");
    sb.AppendLine("}");

    //IEnumerable()方法
    sb.AppendLine(" public IEnumerable<"+tableName+"> GetAll()");
    sb.AppendLine("{");
    sb.AppendLine(" string sql = \"select * from "+tableName+"\";");
    sb.AppendLine("DataTable dt = SQLHelper.ExecuteDataTable(sql);");
    sb.AppendLine(" List<"+tableName+"> list = new List<"+tableName+">();");
    sb.AppendLine(" foreach (DataRow row in dt.Rows)");
    sb.AppendLine("{");
    sb.AppendLine("" + tableName + " model = new " + tableName + "();");
    foreach (DataRow row in dt.Rows)
    {
    string col = Convert.ToString(row["COLUMN_NAME"]);
    string dataType = Convert.ToString(row["data_TYPE"]);
    sb.AppendLine("model." + col + " = Convert." + Get(GetType(dataType).ToString()) + "(row[\"" + col + "\"]);");

    }
    sb.AppendLine(" list.Add(model);");
    sb.AppendLine("}");
    sb.AppendLine("return list;");
    sb.AppendLine("}");
    sb.AppendLine("}");
    sb.AppendLine("}");
    File.WriteAllText(@"d:\"+tableName+"DAL.cs",sb.ToString());


    }
    /// <summary>
    /// 数据库类型转换为C#类型
    /// </summary>
    /// <param name="dataType"></param>
    /// <returns></returns>
    private static Type GetType(string dataType)
    {
    switch (dataType.ToLower())
    {
    case "nvarchar":
    case "varchar":
    case "nchar":
    case "char":
    return typeof(string);
    case "int" :
    return typeof(int);
    case "bigint":
    return typeof(long);
    case "bit":
    return typeof(bool);
    case "datetime":
    return typeof(DateTime);
    default:
    return typeof(object);
    }

    }

    private static string Get(string dataType)
    {

    switch (dataType.ToLower())
    {
    case "system.string":
    return "ToString";
    case "system.int32":
    return "ToInt32";
    case "system.int64":
    return "ToInt64";
    case "system.datetime":
    return "ToDateTime";
    case "system.boolean":
    return "ToBoolean";

    default:
    throw new Exception("找不到匹配的数据类型");

    }
    }
    private static void CreatModel(string tableName, DataTable dt)
    {
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("using System;");
    sb.AppendLine("using System.Collections.Generic;");
    sb.AppendLine("using System.Linq;");
    sb.AppendLine("using System.Text;");
    sb.AppendLine("namespace 三层架构Demo.Model");
    sb.AppendLine("{");
    sb.AppendLine("");
    sb.AppendLine("class " + tableName);
    sb.AppendLine("{");

    foreach (DataRow row in dt.Rows)
    {
    string dataType = Convert.ToString(row["DATA_TYPE"]);

    string columnName = Convert.ToString(row["COLUMN_NAME"]);

    sb.AppendLine("public " + GetType(dataType) + " " + columnName + " { get;set;}");
    }
    sb.AppendLine("}");
    sb.AppendLine("}");
    File.WriteAllText(@"d:\" + tableName + ".cs", sb.ToString());
    //MessageBox.Show(sb.ToString());

    }

    private static void CreatBLL(string tableName, DataTable dt)
    {
    StringBuilder sb = new StringBuilder();
    sb.AppendLine("using System;");
    sb.AppendLine("using System.Collections.Generic;");
    sb.AppendLine("using System.Linq;");
    sb.AppendLine("using System.Text;");
    sb.AppendLine("using 三层架构Demo.Model;");
    sb.AppendLine("using 三层架构Demo.DAL;");
    sb.AppendLine("using System.Data.SqlClient;");
    sb.AppendLine("using System.Data;");
    sb.AppendLine("namespace 三层架构Demo.BLL");
    sb.AppendLine("{");
    sb.AppendLine("class " + tableName+"BLL");
    sb.AppendLine("{");
    sb.AppendLine("public int Addnew("+tableName+" model)");
    sb.AppendLine("{");
    sb.AppendLine(" return new "+tableName+"DAL().Addnew(model);");
    sb.AppendLine("}");
    sb.AppendLine(" public int Delete(int id)");
    sb.AppendLine("{");
    sb.AppendLine(" return new "+tableName+"DAL().Delete(id);");
    sb.AppendLine("}");
    sb.AppendLine(" public int Update("+tableName+" model)");
    sb.AppendLine("{");
    sb.AppendLine(" return new " + tableName + "DAL().Update(model);");
    sb.AppendLine("}");
    sb.AppendLine(" public "+tableName+" Get(int id)");
    sb.AppendLine("{");
    sb.AppendLine(" return new "+tableName+"DAL().Get(id);");
    sb.AppendLine("}");
    sb.AppendLine(" public IEnumerable<"+tableName+"> GetAll()");
    sb.AppendLine("{");
    sb.AppendLine(" return new "+tableName+"DAL().GetAll();");
    sb.AppendLine("}");
    sb.AppendLine("}");
    sb.AppendLine("}");
    File.WriteAllText(@"d:\" + tableName + "BLL.cs", sb.ToString());
    }
    }
    }



    总结:
    忽略了很多限制因素,所以代码生成器功能不是很完善。随着要考虑的条件增多,代码生成器越加复杂。但万变不离其中,只要有耐心,继续AppendLine()添加新语句,相信功能会愈加完善。“
    工欲善其事必先利其器“,程序员不仅会用代码生成器,而且知道其原理才是优秀的程序员。切勿”知其然而不知其所以然“。

  • 相关阅读:
    第4月第1天 makefile automake
    第3月30天 UIImage imageWithContentsOfFile卡顿 Can't add self as subview MPMoviePlayerControlle rcrash
    第3月第27天 uitableviewcell复用
    learning uboot fstype command
    learning uboot part command
    linux command dialog
    linux command curl and sha256sum implement download verification package
    learning shell script prompt to run with superuser privileges (4)
    learning shell get script absolute path (3)
    learning shell args handing key=value example (2)
  • 原文地址:https://www.cnblogs.com/fcsh820/p/2357779.html
Copyright © 2011-2022 走看看