眉山市网站建设_网站建设公司_跨域_seo优化
2025/12/23 17:52:54 网站建设 项目流程

需求分析与场景定义

  • 明确代码生成器的目标:生成实体类、API控制器、DTO等常见场景
  • 典型应用场景:快速开发CRUD功能、减少重复编码工作
  • 核心需求:可配置性、模板灵活性、与项目结构无缝集成

具体实现可参考NetCoreKevin的kevin.CodeGenerator模块

基于.NET构建的企业级SaaS智能应用架构,采用前后端分离设计,具备以下核心特性:
前端技术:

  • Vue3前端框架
  • IDS4单点登录系统
  • 一库多租户解决方案
  • 多级缓存机制
  • CAP事件集成
  • SignalR实时通信
  • 领域驱动设计
  • AI智能体框架
  • RabbitMQ消息队列
  • 项目地址:github:https://github.com/junkai-li/NetCoreKevin
    Gitee: https://gitee.com/netkevin-li/NetCoreKevin

第一步:配置模板

模板配置示例如下图所示:
在这里插入图片描述

创建kevin.CodeGenerator模块

ICodeGeneratorService接口定义

using kevin.CodeGenerator.Dto;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;namespace kevin.CodeGenerator
{public interface ICodeGeneratorService{/// <summary>/// 获取区域名称列表/// </summary>/// <returns></returns>Task<List<string>> GetAreaNames();/// <summary>/// 获取区域名称下面的表列表/// </summary>/// <returns></returns>Task<List<EntityItemDto>> GetAreaNameEntityItems(string areaName);/// <summary>/// 生成代码/// </summary>/// <param name="entityItems"></param>/// <returns></returns>Task<bool> BulidCode(List<EntityItemDto> entityItems);}
}

CodeGeneratorService实现

using kevin.CodeGenerator.Dto;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using static Microsoft.CodeAnalysis.CSharp.SyntaxTokenParser;namespace kevin.CodeGenerator
{public class CodeGeneratorService : ICodeGeneratorService{private CodeGeneratorSetting _config;public CodeGeneratorService(IOptionsMonitor<CodeGeneratorSetting> config){_config = config.CurrentValue;}public async Task<List<string>> GetAreaNames(){return _config.CodeGeneratorItems.Select(t => t.AreaName).ToList();}public async Task<List<EntityItemDto>> GetAreaNameEntityItems(string areaName){var area = _config.CodeGeneratorItems.FirstOrDefault(t => t.AreaName == areaName);if (area != default){var entityItems = new List<EntityItemDto>();var path = "..\\..\\" + area.AreaPath.Trim().Replace(".", "\\");// 遍历路径下的所有 .cs 文件 if (!Directory.Exists(path)){throw new ArgumentException($"CodeGeneratorSetting配置:{areaName}{area.AreaPath}不存在");}else{var csFiles = Directory.GetFiles(path, "*.cs", SearchOption.AllDirectories);foreach (var file in csFiles){// 读取文件内容var code = File.ReadAllText(file);var tree = CSharpSyntaxTree.ParseText(code);var root = (CompilationUnitSyntax)tree.GetRoot();// 查找所有类声明var classDeclarations = root.DescendantNodes().OfType<ClassDeclarationSyntax>();foreach (var classDeclaration in classDeclarations){// 检查类是否有 Table 特性if (classDeclaration.AttributeLists.Any(list =>list.Attributes.Any(attr =>attr.Name.ToString() == "Table"))){string description = "";// 检查类是否有 Description 特性var descriptionAttr = classDeclaration.AttributeLists.SelectMany(list => list.Attributes).FirstOrDefault(attr => attr.Name.ToString() == "Description");if (descriptionAttr != null){// 获取特性参数值var arg = descriptionAttr.ArgumentList?.Arguments.FirstOrDefault();if (arg?.Expression is LiteralExpressionSyntax literal){description = literal.Token.ValueText;}}entityItems.Add(new EntityItemDto{AreaName = area.AreaName,EntityName = classDeclaration.Identifier.Text,Description = $"{file}: {description}"});}}}return entityItems;}}return new List<EntityItemDto>();}public async Task<bool> BulidCode(List<EntityItemDto> entityItems){//获取对应的模板文件var iRpTemplate = GetBuildCodeTemplate("IRp");var rpTemplate = GetBuildCodeTemplate("Rp");var iServiceTemplate = GetBuildCodeTemplate("IService");var service = GetBuildCodeTemplate("Service");foreach (var item in entityItems){var area = _config.CodeGeneratorItems.FirstOrDefault(t => t.AreaName == item.AreaName);if (area != default){if (item.EntityName.StartsWith("T", StringComparison.OrdinalIgnoreCase)){item.EntityName = item.EntityName.Substring(1);}WriteCode(new Dictionary<string, string>{{  "%entityName%",item.EntityName},{  "%namespacePath%",area.IRpBulidPath}}, iRpTemplate, $"../../{area.IRpBulidPath.Trim().Replace(".", "\\")}/I{item.EntityName}Rp.cs");WriteCode(new Dictionary<string, string>{{  "%entityName%",item.EntityName},{  "%namespacePath%",area.RpBulidPath}}, rpTemplate, $"../../{area.RpBulidPath.Trim().Replace(".", "\\")}/{item.EntityName}Rp.cs");WriteCode(new Dictionary<string, string>{{  "%entityName%",item.EntityName},{  "%namespacePath%",area.IServiceBulidPath}}, iServiceTemplate, $"../../{area.IServiceBulidPath.Trim().Replace(".", "\\")}/I{item.EntityName}Service.cs");WriteCode(new Dictionary<string, string>{{  "%entityName%",item.EntityName},{  "%namespacePath%",area.ServiceBulidPath}}, service, $"../../{area.ServiceBulidPath.Trim().Replace(".", "\\")}/{item.EntityName}Service.cs");}}return true;}/// <summary>/// 获取对应模板文件/// </summary>/// <param name="name"></param>/// <returns></returns>private string GetBuildCodeTemplate(string name){return File.ReadAllText("..\\..\\" + "Kevin\\kevin.Module\\kevin.CodeGenerator\\BuildCodeTemplate\\" + name + ".txt", encoding: Encoding.UTF8);}/// <summary>/// 生成文件和代码/// </summary>/// <param name="paramters"></param>/// <param name="content"></param>/// <param name="savePath"></param>private void WriteCode(Dictionary<string, string> paramters, string content, string savePath){foreach (var item in paramters){content = content.Replace(item.Key, item.Value);}var dir = Path.GetDirectoryName(savePath);if (!Directory.Exists(dir)){Directory.CreateDirectory(dir);} if (File.Exists(savePath)){Console.WriteLine($"文件{savePath}已存在,跳过生成!");}else{File.WriteAllText(savePath, content, Encoding.UTF8);}}}
}

CodeGeneratorSettingDto

namespace kevin.CodeGenerator.Dto
{public class CodeGeneratorSetting{/// <summary>/// 配置文件相关信息/// </summary>public List<CodeGeneratorItem> CodeGeneratorItems { get; set; } = new();}public class CodeGeneratorItem{/// <summary>/// 区域/// </summary>public string AreaName { get; set; } = "";/// <summary>/// 数据库实体类路径/// </summary>public string AreaPath { get; set; } = "";/// <summary>/// 仓储接口生成路径/// </summary>public string IRpBulidPath { get; set; } = "";/// <summary>/// 仓储生成路径/// </summary>public string RpBulidPath { get; set; } = "";/// <summary>/// 服务接口生成路径/// </summary>public string IServiceBulidPath { get; set; } = "";/// <summary>/// 服务生成路径/// </summary>public string ServiceBulidPath { get; set; } = "";}
}

配置Json文件

  ////代码生成器配置 .转换成/时要和路径一致 请配置好命名空间和路径对应关系"CodeGeneratorSetting": {"CodeGeneratorItems": [{"AreaName": "App.WebApi.v1", //项目命名"AreaPath": "App.Domain.Entities", //实体类路径"IRpBulidPath": "App.Domain.Interfaces.Repositorie.v1", //仓储接口命名空间和路径"RpBulidPath": "App.RepositorieRps.Repositories.v1", //仓储命名空间和路径"IServiceBulidPath": "App.Domain.Interfaces.Services.v1", //服务接口命名空间和路径"ServiceBulidPath": "App.Application.Services.v1" //服务命名空间和路径}]}

服务注入

 services.AddKevinCodeGenerator(options =>{var settings = Configuration.GetRequiredSection("CodeGeneratorSetting").Get<CodeGeneratorSetting>()!;options.CodeGeneratorItems = settings.CodeGeneratorItems;});

使用
在这里插入图片描述
在这里插入图片描述

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询