.NET Core分层架构下CRUD代码自动化生成最优方案咨询
针对.NET三层架构CRUD代码自动化生成的最佳方案
Hey there! 针对你提到的基于实体自动生成CRUD相关代码(模型、控制器、AutoMapper映射、UnitOfWork仓储)的需求,我来分享几个实践中常用的方案,帮你判断哪个最适合你的项目:
方案1:T4模板(传统但成熟的选择)
你之前考虑的T4模板其实是.NET生态里很经典的代码生成方案,虽然入门需要花点时间熟悉语法,但对于这种重复的CRUD场景非常适配。
怎么实现?
T4模板可以通过反射或者直接解析实体类的代码(比如利用Roslyn在模板里分析代码),提取实体的名称、属性信息,然后填充到预设的代码模板中,自动生成对应的文件。
举个简单的T4片段示例(生成UserModel):
<#@ template language="C#" #> <#@ assembly name="System.Core" #> <#@ import namespace="System.Reflection" #> <# var entityType = typeof(User); var modelName = entityType.Name + "Model"; #> public class <#= modelName #> { <# foreach(var prop in entityType.GetProperties()) { #> public <#= prop.PropertyType.Name #> <#= prop.Name #> { get; set; } <# } #> }
优缺点
- ✅ 成熟稳定,.NET官方支持,资料和现成模板多
- ✅ 可以生成任意格式的代码,完全自定义
- ❌ 语法有点“复古”,调试起来不如现代工具方便
- ❌ 模板文件本身是文本文件,没有强类型提示
方案2:Roslyn源代码生成器(现代推荐方案)
如果你用的是.NET 5及以上版本,Roslyn源代码生成器是更推荐的选择。它是编译时执行的代码生成工具,能无缝集成到你的项目构建流程中,生成的代码会直接参与编译,没有运行时开销,而且支持强类型分析。
怎么实现?
- 创建一个类库项目,引用
Microsoft.CodeAnalysis.CSharp和Microsoft.CodeAnalysis.AnalyzersNuGet包 - 实现
ISourceGenerator接口,在Execute方法中分析你的实体类(比如标记了自定义[GenerateCrud]属性的类) - 根据实体的元数据(名称、属性、导航属性等),拼接出模型、控制器、AutoMapper配置、UnitOfWare仓储的代码字符串
- 调用
GeneratorExecutionContext.AddSource方法,将生成的代码添加到项目中
比如生成AutoMapper映射的代码片段:
var mapperConfigCode = $@" public class {entityName}Profile : Profile {{ public {entityName}Profile() {{ CreateMap<{entityName}, {entityName}Model>(); CreateMap<{entityName}Model, {entityName}>(); }} }}"; context.AddSource($"{entityName}Profile.g.cs", SourceText.From(mapperConfigCode, Encoding.UTF8));
优缺点
- ✅ 编译时生成,无缝集成项目,没有运行时依赖
- ✅ 利用Roslyn的强类型分析,能准确获取实体的所有元数据(包括属性类型、修饰符、注释等)
- ✅ 调试和维护更友好,支持IDE提示
- ❌ 相对于T4,学习曲线稍陡,但官方文档和示例很完善
方案3:自定义脚手架工具(灵活性最高)
如果你的需求非常定制化,也可以自己写一个小型的控制台工具,利用Roslyn或者反射读取实体项目的程序集,然后通过模板引擎(比如Razor、Scriban)生成代码文件,手动或者通过命令行触发生成。
优缺点
- ✅ 完全自定义,不受限于T4或Roslyn的框架
- ✅ 可以做成通用工具,复用在多个项目中
- ❌ 需要额外维护一个工具项目,初期开发成本高
针对你的需求的推荐
结合你提到的“多数代码结构一致,仅少数特殊控制器需手动编写”的场景,我推荐优先尝试Roslyn源代码生成器:
- 它更适合现代.NET项目,尤其是你用的三层架构+Angular的栈
- 生成的代码直接编译到项目中,不需要手动处理文件
- 可以通过自定义属性(比如
[GenerateCrud])灵活控制哪些实体需要生成代码
如果觉得Roslyn的学习成本有点高,也可以先从T4模板入手,找一些现成的.NET CRUD T4模板修改,快速落地需求。
额外提示
- 不管用哪种方案,都可以先把你手动写的代码抽象成模板,替换掉实体名称、属性这些变量,再用工具填充变量生成代码
- 对于导航属性(比如User里的
IEnumerable<Task>),可以在生成模板里添加判断逻辑,决定是否保留到Model中 - 生成控制器时,可以统一注入UnitOfWork,避免重复的构造函数代码
内容的提问来源于stack exchange,提问作者Pablo
相关产品推荐
相关产品推荐

