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

Posted noert

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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.TableNames";
                    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 + "\\\\" + $"prefixBaseitem.TableNameDto.cs";

                    //保存文件
                    FileHelper.Save(fileName, result);
                
            
            return ResultTo.Success("生成成功");
        

让我们看看效果

 

 

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

 

 



 

以上是关于RazorEngine.NetCore 相见恨晚,它让我彻底放弃了T4模板的主要内容,如果未能解决你的问题,请参考以下文章

macdown精品推荐|让人相见恨晚的优质macOS软件

这段代码很Pythonic | 相见恨晚的 itertools 库

这段代码很Pythonic | 相见恨晚的 itertools 库

相见恨晚的网站

你有哪些相见恨晚的Chrome 扩展?

相见恨晚的 scala