• RazorEngine.NetCore 相见恨晚,它让我彻底放弃了T4模板


       在dbfrist 时代,用T4模板生成代码,貌似还没有感觉到别扭。但是到了codefrist 后,我想要实体生成生成备注,我就得想方设法的去把备注弄到数据库,然后 还要处理模型中类型像枚举这种属性,渐渐的感觉到了吃力。要不换种方式吧,想着去反射实体,但是用T4去处理这种反射,还是感觉到有点吃力,就觉得能不能直接像我们直接写后台程序一样去解析,后面想到了Razor 引擎,经过进一步的了解,发现大神封装了一个组件 RazorEngine.NetCore,他很好的解决了我的问题。
       下面就让我们来了解下这个组件吧,先让我们得到这个组件如图

      有了组件,我们先去编写对应自己业务的模板先吧,就比如我这个我创建一个AddDto,我创建的模板如下:

    @*@model LazyBoy.Dtos.DbTableDto*@
    @using LazyBoy.Dtos;
    @using LazyBoy.Extensions;
    @using LazyBoy.Enums;
    
    using System;
    using AutoMapper;
    using Domain.Models.Enum;
    using Domain.Models.Entitys;
    using Sy.ExpressionBuilder.Modules;
    using System.ComponentModel.DataAnnotations;
    using Sy.ExpressionBuilder.Modules;
    using Domain.Models.Entitys;
    using AutoMapper;
    using Domain.Models.Enum;
    
    
    namespace @GeneratorConfig.DtoNameSpaceName
    {
        /// <summary>
        /// @Model.Remark
        ///</summary>
        [AutoMap(typeof(@(@StringExtension.FirstToUp(@Model.TableName))), ReverseMap = true)]
        public partial class  BaseAdd@(@StringExtension.FirstToUp(@Model.TableName))Dto
        {
        @foreach (var pm in @Model.DbColumns)
        {
        @if ((pm.ColumnName.ToLower() != "id"&&(pm.PropertyType == EnumPropertyType.Field || pm.PropertyType == EnumPropertyType.Enum) ))
        {
    
            @:/// <summary>
            @:/// @pm.Remark
            @:/// </summary>
            @:[Display(Name ="@(pm.Remark)")]
            @if (pm.IsRequired)
            {
            @:[Required(ErrorMessage ="@(pm.Remark)不能为空")]
            }
            @if (pm.StringLengthMax!=0)
            {
            @:[StringLength(@(pm.StringLengthMax), MinimumLength =@(pm.StringLengthMin), ErrorMessage = "@(pm.Remark)的长度为{2}至{1}个字符")]
            }
            else if (pm.StringLengthMin!=0)
            {
            @:[StringLength(@(pm.StringLengthMin), ErrorMessage = "@(pm.Remark)的长度至少为{1}个字符")]
            }
            @if(pm.RangeMax!=null)
            {
            @:[Range(@(pm.RangeMax), MinimumLength =@(pm.RangeMin), ErrorMessage="@(pm.Remark)的范围在{1}至{2}之间")]
            }
            @if(pm.Regular!=null)
            {
            @:[RegularExpression("@(pm.Regular)", ErrorMessage = "@(pm.Remark)@(pm.ErrorMessage)")]
            }
            @:public virtual @pm.ColumnType @(pm.IsNullable==true?"?":"")  @StringExtension.FirstToUp(pm.ColumnName) { get;set;}
    
        }
        }
        }
    }

     温馨提示,代码头部这个引用后台返回的实体的这个,我们编写的时候放出来,这样我们就可以像写Razor 视图一样了,后面生成代码的注释掉。

     有了模板后,我们就可以生成我们要的AddDto了,在起始项(.net6 直接在Program) 添加并且编译我们的模板,如下:
     

                //打开并且读取模板
                string template = File.ReadAllText(filePath); //CreateDto.cshtml
                var nameKey = templateName.ToLower().Replace(".cshtml", "");
                //添加模板
                Engine.Razor.AddTemplate(nameKey, template);
                //编译模板
                Engine.Razor.Compile(nameKey, null);

     然后我们根据反射拿到实体类库的解析类,传给引擎就好了
     

     var result = Engine.Razor.Run(templateName.ToLower(), null, item);
    templateName.ToLower(),对应我们添加模板的key,item对应单个实体的解析类,下面给出我的示例代码:
     /// <summary>
            /// 创建所有类型Dto
            /// </summary>
            /// <returns></returns>
            [HttpGet]
            public IResultModel CreateAllBaseDto()
            {
                CreateDtoManager dtoManager = new CreateDtoManager();
                var dbTables = dtoManager.GetDbTable();
                var dtoPath = _configuration.GetSection("DbConfigInfo")["CodeResourcePath"];
                var templateNames = _configuration.GetSection("DbConfigInfo")["BaseDtoTemplateName"];
                foreach (var item in dbTables)
                {
                    foreach (var templateName in templateNames?.Split(',').ToList())
                    {
                        var result = Engine.Razor.Run(templateName.ToLower(), null, item);
                        var filePath = $"{dtoPath}/BaseDtos/{item.SchemaName.GetPath('_')}/{item.TableName}s";
                        var prefix = "";
                        if (templateName.Contains("add", StringComparison.OrdinalIgnoreCase))
                            prefix = "Add";
                        if (templateName.Contains("all", StringComparison.OrdinalIgnoreCase))
                            prefix = "All";
                        if (templateName.Contains("edit", StringComparison.OrdinalIgnoreCase))
                            prefix = "Edit";
                        string fileName = filePath + "\\" + $"{prefix}Base{item.TableName}Dto.cs";
    
                        //保存文件
                        FileHelper.Save(fileName, result);
                    }
                }
                return ResultTo.Success("生成成功");
            }

    让我们看看效果

     然后保存在本地就大功告成了,我集中放到了一个文件夹,这样方便直接拷贝替换(集成到项目可以直接替换,但是有覆盖风险,没敢),后面看看最后的成果。



  • 相关阅读:
    剑指 Offer 26. 树的子结构
    99. 恢复二叉搜索树(困难)
    93. 复原IP地址
    剑指 Offer 20. 表示数值的字符串
    100. 相同的树
    336. 回文对
    12. 整数转罗马数字(贪心!)
    块链技术在数据中心应用的成与败
    新型大脑启发式学习方法来了,可帮助人工神经网络节省内存和能量
    混合多云为何具有技术优势
  • 原文地址:https://www.cnblogs.com/noert/p/15769857.html
Copyright © 2020-2023  润新知