惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Recent Announcements
Recent Announcements
博客园 - Franky
博客园 - 三生石上(FineUI控件)
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
人人都是产品经理
人人都是产品经理
博客园 - 【当耐特】
L
LangChain Blog
Stack Overflow Blog
Stack Overflow Blog
H
Help Net Security
爱范儿
爱范儿
罗磊的独立博客
博客园_首页
美团技术团队
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
月光博客
月光博客
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
量子位
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 叶小钗
V
Visual Studio Blog
T
Tailwind CSS Blog

博客园 - 青争竹马

非 Web 应用程序中的用户机密 sortablejs 拖拽库 在Vue 组合模式下的使用 引用非当前解决方案sln的项目csproj编译报错 Windows 剪贴板与远程桌面共享失效 在浏览器F12中使用debugger调试选择不到的元素 Linux Debian 通过 /etc/profile 设置环境变量 Monorepo 之 Yarn Workspaces 中使用 npm-run-all 一次同时运行多个项目 UniApp 反向代理配置 - 本地开发解决跨域问题 Data is Null. This method or property cannot be called on Null values. Install Kibana with Docker Centos7重装Python和Yum SignalR, No Connection with that ID,IIS SQL Server Management Studio IDE中可以命中的索引是Index Seek但是在写的程序中却是Index Scan ssh-copy-id 之后ssh还是提示输入密码的问题 Docker容器中连接Sql Server数据库报错 provider: SSL Provider, error: 31 - Encryption(ssl/tls) handshake failed cdn.devolutions.net ip foxmail windows 每次打开都需要登录账号 错误 NU1105 找不到“xx.csproj”的项目信息。如果使用 Visual Studio,这可能是因为该项目已被卸载或不属于当前解决方案,因此请从命令行运行还原。否则,项目文件可能无效或缺少还原所需的目标。 xxx xxx.csproj Jenkins 构建踩坑经历 log4net SmtpAppender 踩坑总结
创建 abp.io Abp VNext 项目
青争竹马 · 2026-04-26 · via 博客园 - 青争竹马

通过源代码模板创建项目

下载官网源代码 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");