zoukankan      html  css  js  c++  java
  • codesmith 模板

    近来 两天自身 写了个基本 的ORM框架,特别的Easy,但是没有相应的代码生成工具,于是就很杯具了!
      于是乎,花费了一天的时间学习并写了一个CodeSmith可以运用 的模板。在此记录下CodeSmith的学习笔记。
      所用工具: CodeSmith Professional v5.1.3.8510,代码示例所有 是以C#为例。
      一、            工具配置
      CodeSmith默认是不支撑 中文的,那么咱们 必须要先配置 使其支撑 中文显示,保存。并且要能够在生成文件中支撑 中文。
      1. [Tools->Options...->Studio->Editor->Enable unicode]将这个选项勾上,那么CodeSmith就可以显示和保存中文了。
      2. 在你的模板的最前面的一句话,C#为例:
       <%@ CodeTemplate TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="Template description here." %>
      中参加 ResponseEncoding="UTF-8" 的标签。将会使得生成的文件也支撑 中文。
      1. [Tools->Options...->Studio->Editor->Convert tab to]去掉这个的勾选,就是不运用 空格来替换Tab。
      二、            模板区域说明
      CodeSmith的模板分为六个区域:模板说明区域,属性配置 区域,注册模板区域,引用声明区域,模板区域,函数区域。
      (一)        模板说明区域,只有一句话:
       <%@ CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src="" Inherits="" Debug="False" CompilerVersion="v3.5" Description="这里是模板说明" %>
      (二)        属性配置 区域
      你模板须要 那些外接参数,都可以写在这里。当然还有一些其他的参数须要 些在函数区域,在后面咱们 再来描述。
      1)   String类型参数声明:
      <%@ Property Default="AAA" Optional="True" Category="输入参数" Description="这是一个字符串型的参数" %>
    2)   Bool类型参数声明:
      <%@ Property Default="True" Optional="False" Category="输入参数" Description="这是一个布朗型的参数" %>
      3)   DatabaseSchema类型参数声明:
      <%@ Property Category="Context" Description="这是一个数据库" %>
      4)   TableSchemaCollection类型参数声明:
      <%@ Property Category="Context" Description="这是一个数据表集合" %>
      5)   TableSchema类型参数声明:
      <%@ Property Category="Context" Description="这是一个数据表" %>
      (三)        注册模板区域
      在你的模板中可以调用其他的模板用于生成,当然,你调用的模板所须要 的参数你都必须给出。注册代码如下:
      <%@ Register Template="B.cst" MergeProperties="False" ExcludeProperties="" %>
      这就是将B模板注册到A模板中。
      (四)        引用声明区域
      在这里要将咱们 运用 到了的运用 集都在这里写出来,假如 运用 到数据库就必须 要添加下面的两个。
    <%@ Assembly %>
    <%@ Import Namespace="SchemaExp lorer" %>

      要自身 控制输出文件的话就须要 添加:<%@ Import Namespace="System.IO" %>
      (五)        模板区域
      这里就是咱们 控制要输出的文件或者界面的内容。
      直接输出值为<%= ThisIsString %>
      调用代码为<% if (ThisIsBool) { %>A<% } %> 假如 ThisIsBool为true则输出A。
      (六)        函数区域
      在这里咱们 可以定义咱们 自身 的函数,用于一些庞杂 的组合、代码的重用等。代码格式和C#完全一样。
      三、            模板编写要领
      A.     直接输出
      在模板区域直接输入文本,就会直接输出的output里面了。
      B.     变量输出

      例如输出ThisIsString的变量值:<%= ThisIsString %>

    再例如输出ThisIsTable的名字:<%= ThisIsTable.Name %>
      C.      调用函数
      例如,假如 输入的ThisIsBool为true就输出A字符。
    <% if (ThisIsBool) { %>A<% } %>
      D.    调用模板
      这里咱们 将在A模板内调用并显示B模板。每个模板都有一个Response来存储模板输出的。模板显示是调用Render()要领 来完成的。
    <% for(int i = 0; i < ThisIsTableList.Count; i++)
    {
        B b = new B();
        b.ThisIsTable = ThisIsTableList[i];
        b.Render(this.Response);
    } %>

      E.      遍历Database或TableCollection内的表
      这里咱们 可以运用 for或者foreach做循环,为了通用性例子所有 运用 for做循环。
      遍历ThisIsDatabase并输出表名
    <% for (int t = 0; t < ThisIsDatabase.Tables.Count; t++) { %>
        <%= ThisIsDatabase.Tables[t].Name %>
    <% } %>

      F.      遍历Table的列
      遍历ThisIsTable的列并且生成类似如下格式的语句:
    //数据库类型:DbType.int
    private int _ID;

      这里调用了一个要领 DataType2CSharpType(System.Data.DbType dbType)在后面将会讲到。
    <% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
        //数据库类型:DbType.<%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %>
        private <%= DataType2CSharpType(ThisIsTable.Columns[c].DataType) %> _<%= ThisIsTable.Columns[c].Name %>;
       <% } %>
     

    //数据库类型:DbType.int
        private int _ID;
       
        //数据库类型:DbType.int
        private int _ClassID;
       
        //数据库类型:DbType.string
        private string _StudentName;

      G.     遍历Table的PK
      <% for (int c = 0; c < ThisIsTable.PrimaryKey.MemberColumns.Count; c++) { %>
      主键<%= c %>:<%= ThisIsTable.PrimaryKey.Name %>
        <%= ThisIsTable.PrimaryKey.Table.Name %>.<%= ThisIsTable.PrimaryKey.MemberColumns[c].Name %>
    <% } %>

      输出结果 :
      主键0:PK_Student
      Student.ID
      H.    遍历Table的FK(Table自身 是外键表<即Table为明细表>)
      这里说明下,下面的代码仅仅只是对FK里面的列是一对一的有效,假如 是多对多的FK须要 修改下面的0的地点 为循环即可。
      <% for (int c = 0; c < ThisIsTable.ForeignKeys.Count; c++) { %>
      外键<%= c %>:<%= ThisIsTable.ForeignKeys[c].Name %>
      外键<%= c %>对应的列
        <% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
             <%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name  %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name  %> <——来自于 <%= ThisIsTable.ForeignKeys[c].PrimaryKeyTable.Name  %>.<%= ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns[0].Name  %>
        <% } %>
    <% } %>
     

    外键0:FK_Student_Class
      外键0对应的列
      I.        遍历Table的FK(Table自身 是主键表<即Table为父表>)
      <% for (int c = 0; c < ThisIsTable.PrimaryKeys.Count; c++) { %>
      其他表外键<%= c %>:<%= ThisIsTable.PrimaryKeys[c].Name %>
      其他表外键<%= c %>对应的列:
        <% for (int i = 0; i < ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
             <%= ThisIsTable.PrimaryKeys[c].PrimaryKeyTable.Name  %>.<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns[0].Name  %> 作用于——> <%= ThisIsTable.PrimaryKeys[c].ForeignKeyTable.Name  %>.<%= ThisIsTable.PrimaryKeys[c].ForeignKeyMemberColumns[0].Name  %>
        <% } %>
    <% } %>

      输出结果:
      其他表外键0:FK_ExamScore_Student
      其他表外键0对应的列:
      Student.ID 作用于——> ExamScore.StudentID
      四、            函数区域用法
      之前咱们 提到过,有些参数必须要写在函数区域中。当然这些参数就是须要 有一些其他组件支撑 的参数了,比如弹出一个窗口挑选 文件,或者弹出一个挑选 文件夹的窗体,用于输入的参数。
      1)    添加一个挑选 目录的输入参数
      下面咱们 就是定义了一个输入参数OutputDirectory,在运行的输入参数界面,点击这个参数的输入框就会弹出一个挑选 目录的窗口。
        private string templateOutputDirectory = "";
       
        [Editor(typeof(System.Windows.Forms.Design.FolderNameEditor), typeof(System.Drawing.Design.UITypeEditor))]
        [Optional, NotChecked]
        [Category("OutputInfo")]
        [Description("输出结果的目录。")]
        [DefaultValue("")]
        public string OutputDirectory
        {
            get
            {
                if (string.IsNullOrEmpty(templateOutputDirectory))
                {
                    return "C:\\"+ (ThisIsDatabase!= null ? ThisIsDatabase.Name : "Output");
                }
                else
                {
                    return templateOutputDirectory;
                }
            }
            set
            {
                if (value.EndsWith("\\")) value = value.Substring(0, value.Length - 1);
                templateOutputDirectory = value;
            }
        }
     

      添加一个挑选 文件的输入参数
      下面咱们 就是定义了一个输入参数OutputFile,在运行的输入参数界面,点击这个参数的输入框就会弹出一个挑选 文件的窗口。
        private string templateOutputFile;
       
        [Editor(typeof(System.Windows.Forms.Design.FileNameEditor), typeof(System.Drawing.Design.UITypeEditor))]   
        [Optional, NotChecked]
        [Category("OutputInfo")]
        [Description("输出文件")]
        [DefaultValue("")]
        public string OutputFile
        {
            get
            {
                if (string.IsNullOrEmpty(templateOutputFile))
                {
                    return "C:\\"+ (ThisIsDatabase != null ? ThisIsDatabase.Name + ".cs" : "Output.cs");
                }
                else
                {
                    return templateOutputFile;
                }
            }
            set
            {
                templateOutputFile = value;
            }
        }

      3)    将数据库类型转化为C#类型的函数
      输入DbType的类型转化后输出C#的类型的字符串。这个函数很常用到。
        public string DataType2CSharpType(System.Data.DbType dbType)
        {
            switch (dbType)
            {
                case DbType.AnsiString:
                    return "string";
                case DbType.AnsiStringFixedLength:
                    return "string";
                case DbType.Binary:
                    return "byte[]";
                case DbType.Boolean:
                    return "bool";
                case DbType.Byte:
                    return "byte";
                case DbType.Currency:
                    return "decimal";
                case DbType.Date:
                    return "DateTime";
                case DbType.DateTime:
                    return "DateTime";
                case DbType.DateTime2:
                    return "DateTime";
                case DbType.DateTimeOffset:
                    return "DateTime";
                case DbType.Decimal:
                    return "decimal";
                case DbType.Double:
                    return "double";
                case DbType.Guid:
                    return "Guid";
                case DbType.Int16:
                    return "short";
                case DbType.Int32:
                    return "int";
                case DbType.Int64:
                    return "long";
                case DbType.Object:
                    return "object";
                case DbType.SByte:
                    return "sbyte";
                case DbType.Single:
                    return "float";
                case DbType.String:
                    return "string";
                case DbType.StringFixedLength:
                    return "string";
                case DbType.Time:
                    return "DateTime";
                   
                case DbType.UInt16:
                    return "ushort";
                case DbType.UInt32:
                    return "uint";
                case DbType.UInt64:
                    return "ulong";
                case DbType.VarNumeric:
                    return "decimal";
                case DbType.Xml:
                    return "string";
                default:
                    return "object";
            }
        }

    获取数据库类型的字段在C#中的默认值
      输入DbType的类型转化后输出C#的类型的默认值。这个函数和上面那个差不多,只是有些时候配置 了值后期盼 给个默认值而已。
        public string DataTypeDefaultValue(System.Data.DbType dbType)
        {
            switch (dbType)
            {
                case DbType.AnsiString:
                    return "String.Empty";
                case DbType.AnsiStringFixedLength:
                    return "String.Empty";
                case DbType.Binary: //Answer modified was just 0
                    return "new byte[] {}";
                case DbType.Boolean:
                    return "false";
                case DbType.Byte: //Answer modified was just 0
                    return "(byte)0";
                case DbType.Currency:
                    return "0";
                case DbType.Date:
                    return "DateTime.MinValue";
                case DbType.DateTime:
                    return "DateTime.MinValue";
                case DbType.DateTime2:
                    return "DateTime.MinValue";
                case DbType.DateTimeOffset:
                    return "DateTime.MinValue";
                case DbType.Decimal:
                    return "0.0m";
                case DbType.Double:
                    return "0.0f";
                case DbType.Guid:
                    return "Guid.Empty";
                case DbType.Int16:
                    return "(short)0";
                case DbType.Int32:
                    return "(int)0";
                case DbType.Int64:
                    return "(long)0";
                case DbType.Object:
                    return "new object()";
                case DbType.SByte:
                    return "(sbyte)0";
                case DbType.Single:
                    return "0F";
                case DbType.String:
                    return "String.Empty";
                case DbType.StringFixedLength:
                    return "String.Empty";
                case DbType.Time:
                    return "new DateTime(1900,1,1,0,0,0,0)"; //return "DateTime.MaxValue";
                case DbType.UInt16:
                    return "(ushort)0";
                case DbType.UInt32:
                    return "(uint)0";
                case DbType.UInt64:
                    return "(ulong)0";
                case DbType.VarNumeric:
                    return "(decimal)0";
                case DbType.Xml:
                    return "String.Empty";
                default:
                    return "null";
            }
        }
     

     5)    文件输出函数
      当然了,做了这么多的工作,结尾 肯定是期盼 输出成文件咯,在前面咱们 已经说过了,对于输出的结果是调用Render()要领 ,那么咱们 只须要 在Render()要领 里面输出文件就可以了。
        public override void Render(TextWriter writer)
        {
            if (!Directory.Exists(OutputDirectory))
                Directory.CreateDirectory(OutputDirectory);
            StreamWriter BaseFile = new StreamWriter(OutputFile, false);
            base.Render(writer);
            BaseFile.Close();
        }

      当然了,咱们 也可以再嵌入的其他模板里面调用这些输出的要领 ,从而达到输出多个文件的目标 ,这里就不再细致 的写代码了。
      另附上完整的B的代码:
    <%@  CodeTemplate ResponseEncoding="UTF-8" TargetLanguage="Text" Src=""  Inherits="" Debug="False" CompilerVersion="v3.5" Description="这里是模板说明"  %>
    <%@ Property Category="Context" Description="这是一个数据表" %>
     
    <%@ Assembly %>
    <%@ Import Namespace="SchemaExp lorer" %>

      数据表名称:<%= ThisIsTable.Name %>
    <% for (int c = 0; c < ThisIsTable.PrimaryKey.MemberColumns.Count; c++) { %>
    主键<%= c %>:<%= ThisIsTable.PrimaryKey.Name %>
        <%= ThisIsTable.PrimaryKey.Table.Name %>.<%= ThisIsTable.PrimaryKey.MemberColumns[c].Name %>
    <% } %>
     
    <% for (int c = 0; c < ThisIsTable.ForeignKeys.Count; c++) { %>
     

    外键<%= c %>:<%= ThisIsTable.ForeignKeys[c].Name %>
      外键<%= c %>对应的列
        <% for (int i = 0; i < ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
             <%= ThisIsTable.ForeignKeys[c].ForeignKeyTable.Name  %>.<%= ThisIsTable.ForeignKeys[c].ForeignKeyMemberColumns[0].Name  %> <——来自于 <%= ThisIsTable.ForeignKeys[c].PrimaryKeyTable.Name  %>.<%= ThisIsTable.ForeignKeys[c].PrimaryKeyMemberColumns[0].Name  %>
        <% } %>
    <% } %>
     
    <% for (int c = 0; c < ThisIsTable.PrimaryKeys.Count; c++) { %>

      其他表外键<%= c %>:<%= ThisIsTable.PrimaryKeys[c].Name %>
      其他表外键<%= c %>对应的列:
        <% for (int i = 0; i < ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns.Count; i++) { %>
             <%= ThisIsTable.PrimaryKeys[c].PrimaryKeyTable.Name  %>.<%= ThisIsTable.PrimaryKeys[c].PrimaryKeyMemberColumns[0].Name  %> 作用于——> <%= ThisIsTable.PrimaryKeys[c].ForeignKeyTable.Name  %>.<%= ThisIsTable.PrimaryKeys[c].ForeignKeyMemberColumns[0].Name  %>
        <% } %>
    <% } %>

      数据表Select语句:
    private const String SelectString = @"
                SELECT
                    <% for (int c = 0; c < ThisIsTable.Columns.Count; c++) { %>
                    [<%= ThisIsTable.Columns[c].Name %>]<% if (c < ThisIsTable.Columns.Count - 1) { %>,<% } %>
                    <% } %>
                FROM [<%= ThisIsTable.Name %>] WHERE 1 = 1 ";
     


    作者:水木    
     
  • 相关阅读:
    Android 重写系统Crash处理类,保存Crash信息到SD卡 和 完美退出程序的方法
    LeetCode第二十四题-交换链表中节点值
    LeetCode第二十三题-合并n个有序链表
    LeetCode第二十二题-创建n对括号
    LeetCode第二十一题-对两个有序链表排序
    LeetCode第二十题-有效的括号
    LeetCode第十九题-链表节点的删除
    LeetCode第十八题-四数之和
    LeetCode第十七题-电话号码的字母组合
    LeetCode第十六题-找出数组中三数之和最接近目标值的答案
  • 原文地址:https://www.cnblogs.com/hsapphire/p/1655984.html
Copyright © 2011-2022 走看看