创建 abp.io Abp VNext 项目

通过源代码模板创建项目

下载官网源代码 https://github.com/abpframework/abp

代码

using System;
using System.IO;
using System.Text;
using System.Text.RegularExpressions;
using System.Xml.Linq;

public class AbpIoAppTemplateCreate
{
    public string VoloAbpVersion { get; set; } = "8.3.4";
    public string SourceCompanyName { get; set; } = "MyCompanyName";
    public string SourceProjectName { get; set; } = "MyProjectName";

    public string TargetCompanyName { get; set; }
    public string TargetProjectName { get; set; }
    public void Run(string sourceDir, string destDir)
    {
        PackageVersions = new Dictionary<string, string>();

        CopyDirectoryWithRename(sourceDir, destDir);
        XElement xml = new XElement("Project",
         //from user in users
         //select new XElement("User",
         //    new XAttribute("id", user.ID),
         //    new XElement("Name", user.Name),
         //    new XElement("Email", user.Email)
         //)
         new XElement("PropertyGroup", new XElement("ManagePackageVersionsCentrally", "true")),
         new XElement("ItemGroup", from item in PackageVersions.OrderBy(x => x.Key) select new XElement("PackageVersion", new XAttribute("Include", item.Key), new XAttribute("Version", item.Value))
        ));


        xml.Save(@$"{destDir}\Directory.Packages.props");
    }
    /// <summary>
    /// 复制文件夹并重命名以特定字符串开头的文件夹和文件。
    /// </summary>
    /// <param name="sourceDir">源文件夹路径(例如:@"C:\Source")。</param>
    /// <param name="destDir">目标文件夹路径(例如:@"D:\Destination")。</param>
    private void CopyDirectoryWithRename(string sourceDir, string destDir)
    {

        // 检查源目录是否存在 
        if (!Directory.Exists(sourceDir))
        {
            throw new DirectoryNotFoundException($"源目录不存在: {sourceDir}");
        }
        //if (Directory.Exists(destDir))
        //{
        //    throw new DirectoryNotFoundException($"目标目录已存在: {destDir}");
        //}

        // 创建目标根目录(如果不存在)
        Directory.CreateDirectory(destDir);

        // 复制当前目录中的所有文件
        foreach (string sourceFilePath in Directory.GetFiles(sourceDir))
        {
            // 获取文件名并应用重命名逻辑
            string fileName = Path.GetFileName(sourceFilePath);
            string newFileName = ApplyNameReplacement(fileName); // 应用名称替换
            string destFilePath = Path.Combine(destDir, newFileName);

            // 复制文件,允许覆盖已存在的文件
            File.Copy(sourceFilePath, destFilePath, true);

            ReplaceFileContent(destFilePath); // 处理文件内容 
        }

        // 递归复制所有子目录 
        foreach (string sourceSubDir in Directory.GetDirectories(sourceDir))
        {
            // 获取子目录名并应用重命名逻辑 
            string subDirName = Path.GetFileName(sourceSubDir);
            string newSubDirName = ApplyNameReplacement(subDirName); // 应用名称替换 
            string destSubDirPath = Path.Combine(destDir, newSubDirName);

            // 递归调用以处理子目录
            CopyDirectoryWithRename(sourceSubDir, destSubDirPath);
        }


    }

    Dictionary<string, string> PackageVersions;

    /// <summary>
    /// 应用名称替换逻辑:如果名称以"MyCompanyName"开头,则替换为"TargetCompanyName.TargetProjectName"。
    /// </summary>
    /// <param name="originalName">原始名称。</param>
    /// <returns>替换后的名称。</returns>
    private string ApplyNameReplacement(string originalName)
    {
        string oldPrefix = $"{SourceCompanyName}.{SourceProjectName}";
        string newPrefix = $"{TargetCompanyName}.{TargetProjectName}";

        string oldPrefix2 = $"{SourceProjectName}";
        string newPrefix2 = $"{TargetProjectName}";


        // 检查名称是否以指定前缀开头
        if (originalName.StartsWith(oldPrefix, StringComparison.OrdinalIgnoreCase)) // 忽略大小写
        {
            // 替换前缀:移除旧前缀,添加新前缀
            return newPrefix + originalName.Substring(oldPrefix.Length);
        }

        if (originalName.StartsWith(oldPrefix2, StringComparison.OrdinalIgnoreCase)) // 忽略大小写
        {
            // 替换前缀:移除旧前缀,添加新前缀
            return newPrefix2 + originalName.Substring(oldPrefix2.Length);
        }
        return originalName; // 如果不匹配,返回原名称
    }

    void ReplaceFileContent(string filePath)
    {
        // 跳过二进制文件 [4]()
        string ext = Path.GetExtension(filePath).ToLower();
        if (ext == ".dll" || ext == ".exe" || ext == ".png" || ext == ".jpg")
            return;

        try
        {
            // 读取并替换内容
            string content = File.ReadAllText(filePath, Encoding.UTF8);

            content = content.Replace("MyCompanyName", TargetCompanyName);
            content = content.Replace("MyProjectName", TargetProjectName);

            if (ext == ".csproj")
            {
                var set = ExtractToHashSet(
                           content,
                           @"(Volo\.Abp[^\\]*?)\.csproj",
                           RegexOptions.IgnoreCase);
                foreach (var item in set)
                {
                    PackageVersions.TryAdd(item.Replace(".csproj", string.Empty), VoloAbpVersion);
                }
            }
            if (ext == ".csproj")
            {
                var set = ExtractToHashSet(
               content,
               @"<PackageReference\s+Include=""(.*?)""\s+Version=""(.*?)""",
               RegexOptions.IgnoreCase);
                foreach (var item in set)
                {
                    var otherPackage = Regex.Replace(item, @"<PackageReference\s+Include=""(.*?)""\s+Version=""(.*?)""", "$1|$2").Split('|');

                    PackageVersions.TryAdd(otherPackage[0], otherPackage[1]);
                }
            }


            content = Regex.Replace(content, @"<PackageReference\s+Include=""(.*?)""\s+Version=""(.*?)""", "<PackageReference Include=\"$1\"");
            content = Regex.Replace(content, @"<ProjectReference.*?(Volo\.Abp[^\\]*?)\.csproj", $"<PackageReference Include=\"$1");
            File.WriteAllText(filePath, content, Encoding.UTF8);
        }
        catch (Exception ex)
        {
            Console.WriteLine($"处理文件 {filePath} 时出错: {ex.Message}");
        }
    }

    public static HashSet<string> ExtractToHashSet(
    string input,
    string pattern,
    RegexOptions options = RegexOptions.None)
    {
        if (string.IsNullOrEmpty(input) || string.IsNullOrEmpty(pattern))
            return new HashSet<string>(StringComparer.OrdinalIgnoreCase); // 或根据需要选 Ordinal/OrdinalIgnoreCase 

        var matches = Regex.Matches(input, pattern, options);
        var set = new HashSet<string>(StringComparer.OrdinalIgnoreCase); // 默认忽略大小写去重;如需区分大小写,改用 StringComparer.Ordinal

        foreach (Match match in matches)
        {
            if (match.Success && match.Groups.Count > 0)
            {
                // 优先取整个匹配(Group[0]),也可指定 Group 名或索引(如 match.Groups["name"].Value)
                string value = match.Value.Trim();
                if (!string.IsNullOrEmpty(value))
                    set.Add(value);
            }
        }

        return set;
    }
}

运行

new AbpIoAppTemplateCreate() { TargetCompanyName= "创建公司名", TargetProjectName= "创建的项目名" }.Run(@"D:\abp源代码目录\templates\app\aspnet-core", @"D:\Demo\NetCore");

posted @ 2026-04-26 18:43  青争竹马  阅读(10)  评论(0)    收藏  举报