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

推荐订阅源

Last Week in AI
Last Week in AI
有赞技术团队
有赞技术团队
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
人人都是产品经理
人人都是产品经理
博客园 - 司徒正美
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 叶小钗
罗磊的独立博客
IT之家
IT之家
博客园 - 三生石上(FineUI控件)
V
Visual Studio Blog
T
Tailwind CSS Blog
大猫的无限游戏
大猫的无限游戏
Hugging Face - Blog
Hugging Face - Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
MyScale Blog
MyScale Blog
J
Java Code Geeks
L
LangChain Blog
S
SegmentFault 最新的问题
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Apple Machine Learning Research
Apple Machine Learning Research
G
Google Developers 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");