c#使用dotliquid创建自定义代码模板

在编写asp.net webapi 项目时,对于常规的curd操作,在实体建立后,ctrl、service等代码基本上都有大致相同的结构,借助dotliquid自行编写代码模板,可减少一些重复的工作

以生成ctrl为例:

引入依赖-DotLiquid

dotnet add package DotLiquid --version 2.3.197

创建替换模板类

CodeGenerator/Models/CtrlTemplateModel.cs
主要用来携带用来替换模板的信息

using DotLiquid;

namespace CodeGenerator.Models;

public class CtrlTemplateModel : ILiquidizable
{
    // 1.项目名
    public string ProjectName { get; set; }

    // 2.业务名
    public string BussName { get; set; }

    // 3. 实体名
    public string EntityName { get; set; }

    // 业务路径
    public string Namespace
    {
        get => ProjectName +"."+ BussName;
    }

    // 实体变量名-实体名小写 -由实体名获取
    public string EntityLowerName
    {
        get => FirstCharToLower(EntityName);
    }

    public static string FirstCharToLower(string input)
    {
        if (string.IsNullOrEmpty(input))
        {
            return input;
        }

        return input.Substring(0, 1).ToLower() + input.Substring(1);
    }

    public object ToLiquid()
    {
        return new
        {
            ProjectName,
            BussName,
            Namespace,
            EntityName,
            EntityLowerName
        };
    }
}

创建用于替换的信息

此json文件用来反序列成Models的c#对象,用来创建携带替换模板信息的实例对象,实际上简单点直接new CtrlTemplateModel 也是可以的
CodeGenerator/JsonTemp/ctrl.json

{
  "ProjectName": "WebApi",
  "BussName": "basebuss",
  "EntityName": "User"
}

创建模板

CodeGenerator/Templates/CtrlTemplate
简单使用 {{ Model.属性 }} ,详细语法请自行查找,基本上需要了解基础替换、循环替换、条件替换和空格处理就可以解决多数问题了。

using AutoMapper;
using CommonHelp.util;
using Microsoft.AspNetCore.Mvc;
using {{ Model.ProjectName }}.basebuss.dto;
using {{ Model.Namespace }}.service;
using {{ Model.ProjectName }}.filters;
using {{ Model.ProjectName }}.migration.models;
using {{ Model.ProjectName }}.page;

namespace {{ Model.Namespace }}.controllers ;


[Transactional]
[ApiController]
[Route("api/[controller]")]
public class {{ Model.EntityName }}Controller(
    ILogger<{{ Model.EntityName }}Controller> logger,
    IMapper mapper,
    I{{ Model.EntityName }}Service service
)
    : ControllerBase
{
    // 请求示例 http://localhost:5026/api/{{ Model.EntityName }}?PageSize=10&PageNum=1&SortField=price,desc;imageUrl,asc&Filter=id:eq:386c60e8373c4c3e99b7aeabfa9b3a86;productId:eq:9988
    /// <summary>
    /// 查找-过滤、分页
    /// </summary>
    [HttpGet]
    public OkObjectResult Get{{ Model.EntityName }}List(
        [FromQuery] {{ Model.EntityName }}Dto? {{ Model.EntityLowerName }}Dto
    )
    {
        if (null != {{ Model.EntityLowerName }}Dto.PageSize && null != {{ Model.EntityLowerName }}Dto.PageNum)
        {
            logger.LogInformation("分页查询dto:{}", ObjectUtil.ToString({{ Model.EntityLowerName }}Dto));
            List<{{ Model.EntityName }}> pageList =
                service.Get{{ Model.EntityName }}List({{ Model.EntityLowerName }}Dto, {{ Model.EntityLowerName }}Dto.PageSize, {{ Model.EntityLowerName }}Dto.PageNum);
            int totalCount = service.TotalCount({{ Model.EntityLowerName }}Dto);

            List<{{ Model.EntityName }}Dto> restList = new List<{{ Model.EntityName }}Dto>();
            mapper.Map(pageList, restList);

            PagedResult<{{ Model.EntityName }}Dto> result = new PagedResult<{{ Model.EntityName }}Dto>(restList, totalCount);

            return Ok(result);
        }
        else
        {
            logger.LogInformation("条件查找:{}", ObjectUtil.ToString({{ Model.EntityLowerName }}Dto));

            List<{{ Model.EntityName }}> dataList = comService.GetCommodities({{ Model.EntityLowerName }}Dto);
            List<{{ Model.EntityName }}Dto> restList = new List<{{ Model.EntityName }}Dto>();
            mapper.Map(dataList, restList);

            return Ok(restList);
        }
    }
    
    /// <summary>
    /// id查找
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpGet("{id}")]
    public OkObjectResult Get{{ Model.EntityName }}(String id)
    {
        logger.LogInformation("id查找:{}", id);
    
        IQueryable<{{ Model.EntityName }}> dataList = comService.Get{{ Model.EntityName }}(id);
        List<{{ Model.EntityName }}Dto> restList = new List<{{ Model.EntityName }}Dto>();
        mapper.Map(dataList, restList);
    
        return Ok(restList);
    }
    

    /// <summary>
    /// 新增
    /// </summary>
    /// <param name="{{ Model.EntityLowerName }}Dto"></param>
    /// <returns></returns>
    [HttpPost]
    public ActionResult<{{ Model.EntityName }}Dto> Post{{ Model.EntityName }}({{ Model.EntityName }}Dto {{ Model.EntityLowerName }}Dto)
    {
        logger.LogInformation("one新增:{}", {{ Model.EntityLowerName }}Dto.ToString());
        if (!ModelState.IsValid)
        {
            logger.LogInformation("校验不通过");
            return BadRequest(ModelState);
        }

        string uid = Guid.NewGuid().ToString().Replace("-", "");
        //重置 id
        {{ Model.EntityLowerName }}Dto.Id = uid;
        {{ Model.EntityName }} {{ Model.EntityLowerName }} = new {{ Model.EntityName }}();
        mapper.Map({{ Model.EntityLowerName }}Dto, {{ Model.EntityLowerName }});

        Boolean result = comService.Add{{ Model.EntityName }}({{ Model.EntityLowerName }});
        return result ? Ok(uid) : BadRequest("新增未成功!");
    }


    /// <summary>
    /// 删除-id
    /// </summary>
    /// <param name="id"></param>
    /// <returns></returns>
    [HttpDelete("{id}")]
    public IActionResult Delete{{ Model.EntityName }}(String id)
    {
        logger.LogInformation("one删除id:{}", id);
        Int32 result = comService.Delete{{ Model.EntityName }}ById(id);
        if (result > 0)
        {
            //if (true) throw new Exception();
            return Ok(result);
        }

        return BadRequest("删除不成功!");
    }


    /// <summary>
    /// 更新-id 实体
    /// </summary>
    /// <param name="id"></param>
    /// <param name="{{ Model.EntityLowerName }}Dto"></param>
    /// <returns></returns>
    [HttpPut("{id}")]
    public async Task<IActionResult> Put{{ Model.EntityName }}({{ Model.EntityName }}Dto {{ Model.EntityLowerName }}Dto)
    {
        logger.LogInformation("edit实体-忽略null属性:{}", ObjectUtil.ToString({{ Model.EntityLowerName }}Dto));
        {{ Model.EntityName }} {{ Model.EntityLowerName }} = new {{ Model.EntityName }}();
        mapper.Map({{ Model.EntityLowerName }}Dto, {{ Model.EntityLowerName }});

        int task = await comService.Update{{ Model.EntityName }}Async({{ Model.EntityLowerName }});
        if (task > 0)
        {
            return Ok(task);
        }

        return Ok("数据未更新:" + task);
    }
    
    
    
    /// <summary>
    /// 部分更新
    /// </summary>
    /// <param name="{{ Model.EntityLowerName }}Dto"></param>
    /// <returns></returns>
    [HttpPatch("{id}")]
    public async Task<IActionResult> Patc{{ Model.EntityName }}({{ Model.EntityName }}Dto {{ Model.EntityLowerName }}Dto)
    {
        logger.LogInformation("edit实体-:{}", ObjectUtil.ToString({{ Model.EntityLowerName }}Dto));
        {{ Model.EntityName }} {{ Model.EntityLowerName }} = new {{ Model.EntityName }}();
        mapper.Map({{ Model.EntityLowerName }}Dto, {{ Model.EntityLowerName }});

        int task = await comService.Update{{ Model.EntityName }}Async({{ Model.EntityLowerName }});
        if (task > 0)
        {
            return Ok(task);
        }

        return Ok("数据未更新:" + task);
    }
}

执行代码

net.9 使用顶级语句 在Program.cs中


// 工作主目录
string workPath = "D:/Datas/WebApi/CodeGenerator/";
//输出主目录
string outPath = "D:/Datas/WebApi/CodeGenerator/";


// 模板文件夹
string templatePath = workPath + "Templates/";

//类模板文件
string templatefilename = "ClassTemplate";

//类模板路径
string templatefile = templatePath + templatefilename;

await createCtrl(workPath, outPath);

async Task createCtrl(string workPath, string outPath)
{
    
    var model = JsonSerializer.Deserialize<CtrlTemplateModel>(File.ReadAllText(workPath + "JsonTemp/ctrl.json"));
  // 读取模板内容,字符串类型
    var template = Template.Parse(File.ReadAllText(templatePath + "CtrlTemplate"));
  // 核心执行方法
    var result = template.Render(Hash.FromAnonymousObject(new { model = model }));
    Console.WriteLine(result);
}
posted @ 2025-06-18 09:09  沉默侍从  阅读(39)  评论(0)    收藏  举报