Files
Hua.Cli/src/Hua.Cli.Core/Hua/Cli/ProjectBuilding/TemplateProjectBuilder.cs
T
ShaoHua 2a6f5f81b7 feat(cli): add ms microservice template support
1. 新增`ms`微服务模板,包含共享项目、微服务、网关、应用等完整架构
2. 为`hua new`命令添加`ms`模板选项并更新文档
3. 将模板文件嵌入CLI项目输出目录
4. 实现微服务模板的项目构建逻辑,自动安装并使用dotnet自定义模板创建项目
2026-07-15 11:30:43 +08:00

130 lines
4.0 KiB
C#

using System;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
using Volo.Abp.Cli.ProjectBuilding.Building;
using Volo.Abp.Cli.Utils;
using Volo.Abp.DependencyInjection;
namespace Volo.Abp.Cli.ProjectBuilding;
public class TemplateProjectBuilder : ITransientDependency
{
protected ISourceCodeStore SourceCodeStore { get; }
protected TemplateProjectBuildPipelineBuilder PipelineBuilder { get; }
protected ICmdHelper CmdHelper { get; }
public TemplateProjectBuilder(
ISourceCodeStore sourceCodeStore,
TemplateProjectBuildPipelineBuilder pipelineBuilder,
ICmdHelper cmdHelper)
{
SourceCodeStore = sourceCodeStore;
PipelineBuilder = pipelineBuilder;
CmdHelper = cmdHelper;
}
public async Task BuildAsync(ProjectBuildArgs args)
{
if (args.DryRun)
{
return;
}
if (args.Template.Name == "ms")
{
await BuildMicroserviceAsync(args);
return;
}
var templatePath = await SourceCodeStore.GetAsync(
args.Template.Name, args.Version);
var context = new ProjectBuildContext(
args.ProjectName,
args.Template.Name,
args.Version,
args.OutputDirectory,
args.DatabaseProvider,
args.UiFramework,
args.ConnectionString,
args.CreateSolutionFolder,
args.NoRandomPort,
templatePath);
var pipeline = PipelineBuilder.Build(context);
await pipeline.ExecuteAsync();
}
private async Task BuildMicroserviceAsync(ProjectBuildArgs args)
{
var templateDir = ResolveTemplateDirectory();
if (!Directory.Exists(templateDir))
{
throw new FileNotFoundException(
$"Microservice template not found at: {templateDir}. " +
"Ensure the 'templates/ms' directory exists alongside the tool.");
}
// Install the template
var installResult = await CmdHelper.RunAsync($"dotnet new install \"{templateDir}\"");
if (!installResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to install microservice template: {installResult.Error}");
}
try
{
// Run dotnet new with the template
var outputDir = args.OutputDirectory;
var projectName = args.ProjectName;
var newResult = await CmdHelper.RunAsync(
$"dotnet new hua-ms -n \"{projectName}\" -o \"{outputDir}\"");
if (!newResult.IsSuccess)
{
throw new InvalidOperationException(
$"Failed to create project: {newResult.Error}");
}
}
finally
{
// Uninstall the template to clean up
await CmdHelper.RunAsync($"dotnet new uninstall \"{templateDir}\"");
}
}
private static string ResolveTemplateDirectory()
{
var assemblyDir = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location) ?? ".";
// First, check relative to the assembly directory (works for published output
// where templates/ms is copied alongside the assembly via CopyToOutputDirectory)
var assemblyRelativePath = Path.Combine(assemblyDir, "templates", "ms");
if (Directory.Exists(assemblyRelativePath))
{
return assemblyRelativePath;
}
// Fall back to upward traversal (works in development when templates/ms
// lives in the repository root above bin/Debug/net9.0)
var directory = new DirectoryInfo(assemblyDir);
while (directory != null)
{
var templatePath = Path.Combine(directory.FullName, "templates", "ms");
if (Directory.Exists(templatePath))
{
return templatePath;
}
directory = directory.Parent;
}
return assemblyRelativePath;
}
}