您好,登录后才能下订单哦!
密码登录
登录注册
点击 登录注册 即表示同意《亿速云用户服务条款》
# NVelocity中怎么实现代码生成功能
## 一、NVelocity简介
### 1.1 什么是NVelocity
NVelocity是Apache Velocity模板引擎的.NET移植版本,它是一个基于Java的模板引擎的C#实现。作为一款强大的模板引擎,NVelocity允许开发者将业务逻辑与展示层分离,通过简单的模板语法实现动态内容生成。
### 1.2 NVelocity的核心特性
- **模板与代码分离**:保持业务逻辑与显示逻辑的独立性
- **简单语法**:类似HTML的模板语法,学习成本低
- **高性能**:模板编译后执行效率高
- **可扩展性**:支持自定义指令和扩展点
- **多领域应用**:适用于网页生成、代码生成、邮件模板等场景
### 1.3 代码生成的应用场景
- 数据库实体类自动生成
- 重复性高的CRUD代码生成
- 项目脚手架创建
- 协议代码生成(如gRPC、Thrift)
- 自动化测试用例生成
## 二、环境准备与基础配置
### 2.1 安装NVelocity
通过NuGet包管理器安装最新版本:
```bash
Install-Package NVelocity
或使用.NET CLI:
dotnet add package NVelocity
using Commons.Collections;
using NVelocity.App;
using NVelocity.Runtime;
// 初始化引擎
var props = new ExtendedProperties();
props.AddProperty(RuntimeConstants.RESOURCE_LOADER, "file");
props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH,
Path.Combine(Directory.GetCurrentDirectory(), "Templates"));
var velocityEngine = new VelocityEngine();
velocityEngine.Init(props);
ProjectRoot/
├── Templates/ # 模板存放目录
│ ├── Entities/ # 实体类模板
│ ├── Repositories/ # 仓储接口模板
│ └── Services/ # 服务类模板
├── Generated/ # 生成代码输出目录
└── CodeGenerator.cs # 生成器主程序
## 单行注释
#*
多行注释
*#
#set($name = "value") ## 变量定义
${variable} ## 变量输出
#set($userName = "John Doe")
#set($age = 30)
#set($isAdmin = true)
用户信息:${userName},年龄:$age
#if($isAdmin)
(管理员权限)
#end
#if($condition)
...
#elseif($otherCondition)
...
#else
...
#end
#foreach($item in $items)
当前项:$item
#if($foreach.hasNext),#end
#end
#macro(renderUser $user)
<div class="user">
<span>$!user.Name</span>
<span>$!user.Age</span>
</div>
#end
## 使用宏
#renderUser($currentUser)
using System;
namespace ${nameSpace}.Entities
{
/// <summary>
/// ${tableComment}
/// </summary>
public class ${entityName}
{
#foreach($column in $columns)
/// <summary>
/// ${column.Comment}
/// </summary>
public ${column.Type} ${column.Name} { get; set; }
#end
}
}
var context = new VelocityContext();
context.Put("nameSpace", "MyProject");
context.Put("entityName", "User");
context.Put("tableComment", "用户信息表");
var columns = new List<object> {
new { Name = "Id", Type = "int", Comment = "主键ID" },
new { Name = "UserName", Type = "string", Comment = "用户名" },
// 其他字段...
};
context.Put("columns", columns);
var writer = new StringWriter();
velocityEngine.MergeTemplate("Entities/EntityTemplate.vm", Encoding.UTF8.HeaderName, context, writer);
File.WriteAllText("Generated/User.cs", writer.ToString());
using System.Collections.Generic;
namespace ${nameSpace}.Repositories
{
public interface I${entityName}Repository
{
${entityName} GetById(int id);
IEnumerable<${entityName}> GetAll();
void Add(${entityName} entity);
void Update(${entityName} entity);
void Delete(int id);
}
}
using ${nameSpace}.Entities;
using ${nameSpace}.Repositories;
namespace ${nameSpace}.Services
{
public class ${entityName}Service
{
private readonly I${entityName}Repository _repository;
public ${entityName}Service(I${entityName}Repository repository)
{
_repository = repository;
}
public ${entityName} GetById(int id) => _repository.GetById(id);
// 其他CRUD方法...
#foreach($method in $customMethods)
public ${method.ReturnType} ${method.Name}(${method.Parameters})
{
// 自定义方法实现
throw new System.NotImplementedException();
}
#end
}
}
## 基础模板(BaseTemplate.vm)
<!DOCTYPE html>
<html>
<head>
<title>${title}</title>
#parse("Includes/Header.vm")
</head>
<body>
#parse($contentTemplate)
</body>
</html>
## 子模板
#set($title = "用户管理")
#set($contentTemplate = "User/List.vm")
#parse("Templates/BaseTemplate.vm")
public class UpperDirective : NVelocity.Runtime.Directive.Directive
{
public override string Name => "upper";
public override DirectiveType Type => DirectiveType.LINE;
public override bool Render(IInternalContextAdapter context, TextWriter writer, INode node)
{
var param = node.GetChild(0).Value(context).ToString();
writer.Write(param.ToUpper());
return true;
}
}
// 注册指令
props.AddProperty(RuntimeConstants.CUSTOM_DIRECTIVES, "upper,Namespace.UpperDirective");
模板缓存:启用模板缓存减少IO
props.AddProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true");
props.AddProperty(RuntimeConstants.RESOURCE_MANAGER_CACHE_ENABLED, "true");
预编译常用模板:对高频使用模板进行预编译
合理设计模板结构:避免过度嵌套和复杂逻辑
try
{
velocityEngine.MergeTemplate(templateName, Encoding.UTF8.HeaderName, context, writer);
}
catch (ResourceNotFoundException ex)
{
// 处理模板未找到
}
catch (ParseErrorException ex)
{
// 处理语法错误
}
catch (MethodInvocationException ex)
{
// 处理方法调用异常
}
using Microsoft.EntityFrameworkCore;
using ${nameSpace}.Entities;
namespace ${nameSpace}.Data
{
public class AppDbContext : DbContext
{
public AppDbContext(DbContextOptions<AppDbContext> options)
: base(options) { }
#foreach($entity in $entities)
public DbSet<${entity}> ${entity}Set { get; set; }
#end
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
// 配置实体关系...
}
}
}
using Microsoft.AspNetCore.Mvc;
using ${nameSpace}.Services;
namespace ${nameSpace}.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class ${entityName}Controller : ControllerBase
{
private readonly ${entityName}Service _service;
public ${entityName}Controller(${entityName}Service service)
{
_service = service;
}
[HttpGet("{id}")]
public IActionResult Get(int id)
{
var entity = _service.GetById(id);
return Ok(entity);
}
// 其他API方法...
}
}
using Xunit;
using ${nameSpace}.Services;
using Moq;
namespace ${nameSpace}.Tests
{
public class ${entityName}ServiceTests
{
private readonly ${entityName}Service _service;
private readonly Mock<I${entityName}Repository> _mockRepo;
public ${entityName}ServiceTests()
{
_mockRepo = new Mock<I${entityName}Repository>();
_service = new ${entityName}Service(_mockRepo.Object);
}
[Fact]
public void GetById_ShouldReturnEntity_WhenExists()
{
// 测试代码...
}
// 其他测试方法...
}
}
问题现象:收到ResourceNotFoundException
- 检查文件路径是否正确
- 确认FILE_RESOURCE_LOADER_PATH
配置
- 验证模板文件是否存在且有读取权限
使用$!variable
语法可避免变量为空时输出:
Hello $!userName ## 当userName为null时输出"Hello "而不是"Hello null"
#set($dollar = "$")
输出美元符号:${dollar}
#set($hash = "#")
输出井号:${hash}
Stopwatch
监控模板渲染时间通过合理应用NVelocity,开发者可以显著提升代码编写效率,将精力集中在核心业务逻辑的实现上。建议从简单模板开始,逐步构建复杂的代码生成系统。 “`
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。