zoukankan      html  css  js  c++  java
  • T4模板 根据实体模型生成具体业务代码

    现有类库名为QS.Model在当前项目中 

    该类库中有6个模型 5个Model都继承自DataAccess

    现在我们使用这5个类生成CRUE

    现在修改BLLTemplate.tt模型的代码

    <#+
    public class BLLTemplate : CSharpTemplate
    {
    
    	string name;
            
        public BLLTemplate(string modelName)
        {
            name = modelName;
        }
    
    	/// <summary>
        /// 获取 生成的文件名,根据模型名定义
        /// </summary>
        public string FileName
        {
            get
            { 
                return string.Format("{0}BLL.cs", EntityName);
            }
        }
    
    	/// <summary>
        /// 实体名称
        /// </summary>
    	public string EntityName
    	{
    		get
    		{
    			return name.Replace("Model", string.Empty);
    		}
    	}
    
    	public override string TransformText()
    	{
    		base.TransformText();
    #>
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    namespace Test.BLL
    {
    	/// <summary>
        /// 逻辑层
        /// </summary>
    	public partial class TestBLL
    	{
            public void Select(){
                
            }
    
            public void Delete(){
    
            }
    
            public void Update(){
    
            }
    
            public void Add(){
    
            }
    	}
    }
    <#+
            return this.GenerationEnvironment.ToString();
    	}
    }
    #>
    

    具体的实现功能自己写在方法里面

    修改文本文档TextTemplate2.tt代码

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ Import Namespace="System.IO" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Reflection" #>
    <#@ Import Namespace="System.Collections.Generic" #>
    <#@ output extension=".txt" #>
    //这个必填 导入T4工具
    <#@ include file="T4Toolbox.tt" #>
    //这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
    <#@ include file="Template/BLLTemplate1.tt" #>
    
    
    <#
        //当前TextTemplate2.tt所在的模板路径
    	var currentPath = Path.GetDirectoryName(Host.TemplateFile);
        //解决方案路径
        string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
        //项目名称
        string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
    
        //实体文件所在路径
        string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
        byte[] fileData = File.ReadAllBytes(modelFile);
        Assembly assembly = Assembly.Load(fileData);
    
        IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
        foreach (Type modelType in modelTypes)
        {
            //实例化bll模板
            BLLTemplate bll= new BLLTemplate(modelType.Name);
            string filePath= Path.Combine(currentPath,"bll", bll.FileName);
            //创建文件
            bll.RenderToFile(filePath);
    
        }
    #>
    

    这里用到了反射 并使用字节的方式加载 是因为在生成过程中出现过 该dll被T4模板占用 故换成此方法

    然后保存或者右键TextTemplate2.tt运行自定义模板

    这里可以调试T4模板在TextTemplate2.tt以打断点的方式运行调试T4模板

    然后就生成成功了 

    但是这里成功生成QS.Models类库下的所有类 我们只需要和数据相关的实体生成

    在EF中 每个实体都有个特性TableAttribute来映射数据的表名 所以我们根据这个特性来判断是否应该生成文件

    所以改动如下

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ Import Namespace="System.IO" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Reflection" #>
    <#@ Import Namespace="System.Collections.Generic" #>
    <#@ assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.DataAnnotations.dll" #>
    <#@ Import Namespace="System.ComponentModel.DataAnnotations.Schema" #>
    <#@ output extension=".txt" #>
    //这个必填 导入T4工具
    <#@ include file="T4Toolbox.tt" #>
    //这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
    <#@ include file="Template/BLLTemplate1.tt" #>
    
    
    <#
        //当前TextTemplate2.tt所在的模板路径
    	var currentPath = Path.GetDirectoryName(Host.TemplateFile);
        //解决方案路径
        string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
        //项目名称
        string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
    
        //实体文件所在路径
        string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
        byte[] fileData = File.ReadAllBytes(modelFile);
        Assembly assembly = Assembly.Load(fileData);
    
        IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
        foreach (Type modelType in modelTypes)
        {
            object[] objAttrs = modelType.GetCustomAttributes(typeof(TableAttribute), true);
            if(objAttrs.Length > 0){
                //实例化bll模板
                BLLTemplate bll= new BLLTemplate(modelType.Name);
                string filePath= Path.Combine(currentPath,"bll", bll.FileName);
                //创建文件
                bll.RenderToFile(filePath);
            }
        }
    #>
    

    由于TableAttribute在命名空间System.ComponentModel.DataAnnotations.Schema所有需要导入该命名空间 但是导入该命名空间后还是报错 我就不知道是什么原因了 所以我就直接加载了这个dll

    如果各位知道不妨告诉博主 博主将感激不尽

    这样 生成代码就搞定了 所有的地方都可以用这样的方式生成

    在视图里面我们需要字段来显示标签就可以这样

    新建Index视图模型叫 IndexViewTemplate.tt

    <#+
    public class IndexViewTemplate : CSharpTemplate
    {
    
    	string name;
        private string[] parme;
        private string[] description;
        public IndexViewTemplate(string modelName,string[] parmes,string[] descriptions)
        {
            name = modelName;
            parme = parmes;
            description  = descriptions;
        }
    
    	/// <summary>
        /// 获取 生成的文件名,根据模型名定义
        /// </summary>
        public string FileName
        {
            get
            { 
                return string.Format("index.cshtml", EntityName);
            }
        }
    
    	/// <summary>
        /// 实体名称
        /// </summary>
    	public string EntityName
    	{
    		get
    		{
    			return name.Replace("Model", string.Empty);
    		}
    	}
            public string View1{
                get{
                    string parmes = null;
                    foreach(string item in description){
                        string newline = "\n";
                        if(item == description[description.Length-1])
                            newline = string.Empty;
                        parmes += $"<th style='text-align:center;'>{item}</th>{newline}";
                    }
                    return parmes;
                }
            }
            public string List{
                get{
                    string parmes = string.Empty;
                    for(int i=0;i<parme.Length;i++){
                        string newline = "\n";
                        if(i == parme.Length-1)
                            newline = string.Empty;
                        parmes += $"row.insertCell({i}).innerHTML = n.{parme[i]};{newline}";
                    }
    
                    return parmes;
                }
            }
    	public override string TransformText()
    	{
    		base.TransformText();
    #>
    
    
    @using LZH.BASE.Models;
    @{
        ViewBag.Title = "Index";
        ViewBag.First = "<#=EntityName #>";
        ViewBag.Second = "<#=EntityName #>";
        Layout = "~/Views/Shared/_Layout.cshtml";
    }
    
    
    @model <#=name#>
    
    <div class="box box-primary">
        <div class="box-header with-border">
            <form class="form-inline">
                <a href="/<#=EntityName #>/Add<#=EntityName #>/" class="btn btn-primary btn-xs"><span class="glyphicon glyphicon-plus-sign"></span> 新增</a>
            </form>
        </div>
    
        <div class="box-body" style="padding:0px">
    
            <table data-toggle="table" id="table" style="border:none;100%;margin-bottom:50px;  text-align:center;" cellpadding="0" cellspacing="0" class="list_table">
                <thead>
                    <tr style="text-align:center;">
                        <#=View1 #>
                    </tr>
                </thead>
                <tbody id="listData"></tbody>
            </table>
    
        </div>
    </div>
    
    
    
    @section Js{
        <script type="text/javascript">
    
            $(document).ready(function () {
                loadData();
            });
            //加载数据
            function loadData() {
                var load = layer.msg('数据加载中,请稍后', { icon: 16, time: 0, shade: [0.3, '#000'] });
                var url = '@Url.Action("GetPageData")';
                $.post(url, function (data) {
                    var table = $("#listData");
                    if (data.length > 0) {
                        $.each(data, function (index, n) {
                            var row = document.createElement('tr');
                            row.className = "tr";
                            <#=List #>
                            row.insertCell(4).innerHTML = "<a title='修改' class='btn btn-primary btn-xs'   style='margin:0 3px'  data-Id=" + n.Id + "  onclick='edit(this)'><span class='fa fa-edit'></span></a>" +
                            "<a title='删除'  class='btn btn-warning btn-xs' style='margin:0 3px' data-Id=" + n.Id + " onclick='delete1(this)'><span class=' fa fa-trash'></span></a>";
                            table.append(row);
                        });
                        tab();
                    }
                    layer.close(load);
                });
            }
    
            function delete1(elemt) {
                layer.confirm('确认删除该数据?', {
                    btn: ['确定', '放弃'] //按钮
                }, function () {
                    var url = '@Url.Action("Delete<#=EntityName #>")';
                    var load = layer.msg('数据提交中,请稍后', { icon: 16, time: 0, shade: [0.3, '#000'] });
                    $.post(url, { userId: $(elemt).data('id') }, function (data) {
                        if (data.Status == 0) {
                            layer.msg("删除成功!", { icon: 1, time: 1000, shade: [0.3, '#000'] }, function () {
                                window.location.href = "@Url.Action("Index")";
                            });
                        } else {
                            layer.msg(data.Message, { icon: 2, time: 1000, shade: [0.3, '#000'] });
                        }
                    });
                });
            }
    
            function edit(elemt) {
                window.location.href = "/<#=EntityName #>/Edit<#=EntityName #>/" + $(elemt).data('id');
            }
    
    
        </script>
    }
    
    
    
    
    
    <#+
            return this.GenerationEnvironment.ToString();
    	}
    }
    #>
    

    然后修改TextTemplate2.tt代码

    <#@ template debug="false" hostspecific="false" language="C#" #>
    <#@ assembly name="System.Core" #>
    <#@ Import Namespace="System.IO" #>
    <#@ import namespace="System.Linq" #>
    <#@ import namespace="System.Text" #>
    <#@ import namespace="System.Reflection" #>
    <#@ Import Namespace="System.Collections.Generic" #>
    <#@ import namespace="System.ComponentModel" #>
    <#@ assembly name="C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.6.1\System.ComponentModel.DataAnnotations.dll" #>
    <#@ Import Namespace="System.ComponentModel.DataAnnotations.Schema" #>
    <#@ output extension=".txt" #>
    //这个必填 导入T4工具
    <#@ include file="T4Toolbox.tt" #>
    //这里填写bll模型的路径 当前TextTemplate2.tt目录下的Template文件夹里的BLLTemplate1.tt
    <#@ include file="Template/IndexViewTemplate.tt" #>
    
    
    <#
        //当前TextTemplate2.tt所在的模板路径
    	var currentPath = Path.GetDirectoryName(Host.TemplateFile);
        //解决方案路径
        string solutionPath = currentPath.Substring(0, currentPath.LastIndexOf("\\"));
        //项目名称
        string projectFullName = currentPath.Substring(currentPath.LastIndexOf("\\") + 1);
    
        //实体文件所在路径
        string modelFile = Path.Combine(solutionPath + @"\QS.Model\\bin\Debug\QS.Model.dll");
        byte[] fileData = File.ReadAllBytes(modelFile);
        Assembly assembly = Assembly.Load(fileData);
    
        IEnumerable<Type> modelTypes = assembly.GetTypes().Where(m => !m.IsAbstract && m.IsClass && m.BaseType != null);
        foreach (Type modelType in modelTypes)
        {
            object[] objAttr = modelType.GetCustomAttributes(typeof(TableAttribute), true);
            if(objAttr.Length > 0){
                List<string> parmes = new List<string>();
                List<string> description = new List<string>();
                //获取公共参数
                var pf = modelType.GetProperties();
                foreach (PropertyInfo item in pf)
                {
                    object[] objAttrs = item.GetCustomAttributes(typeof(NotMappedAttribute), true);
                    if (objAttrs.Length == 0)
                    {
                        parmes.Add(item.Name);
                        object[] objs = item.GetCustomAttributes(typeof(DescriptionAttribute), false);
                        if (objs.Length == 0)    //当描述属性没有时,直接返回名称
                        {
                            description.Add(item.Name);
                        }else{
                            DescriptionAttribute descriptionAttribute = (DescriptionAttribute)objs[0];
                            description.Add(descriptionAttribute.Description);
                        }
                    }
                }
                //创建index
                string modelName = modelType.Name;
                IndexViewTemplate indexTemplate = new IndexViewTemplate(modelName,parmes.ToArray(),description.ToArray());
                var fileName = indexTemplate.FileName;
                var indexFile = Path.Combine(currentPath,"ModelView",indexTemplate.EntityName, indexTemplate.FileName);
                //判断指定文件夹下面是否创建过该文件
                if(!File.Exists(indexFile)){
                    indexTemplate.RenderToFile(indexFile);
                }
            }
        }
    #>
    

    好了这样就行了 增删改查视图都是一样的 不过要注意模板里面的FileName字段,这里的所有文件生成都是根据这个字段来的

    如果你的实体dll有依赖的 引用的其他程序集 需要加载所有的依赖项才可以

    具体参考:https://www.cnblogs.com/zagelover/articles/2726034.html

    提个问题:生成需要反射的dll是出现该文件已锁定是怎么回事 我使用的File.ReadAllBytes()应该不会锁定该文件吧

  • 相关阅读:
    Java设计模式-状态模式(State)
    Java设计模式-备忘录模式(Memento)
    Java设计模式-命令模式(Command)
    Java设计模式-责任链模式(Chain of Responsibility)
    Java设计模式-迭代子模式(Iterator)
    Java设计模式-观察者模式(Observer)
    Java设计模式-模板方法模式(Template Method)
    Java设计模式-策略模式(strategy)
    Java设计模式-享元模式(Flyweight)
    Java设计模式-组合模式(Composite)
  • 原文地址:https://www.cnblogs.com/qs315/p/9365995.html
Copyright © 2011-2022 走看看