CSharp: Iterator Pattern

项目结构:

image

 

/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelleryProcessAggregate.cs
 
 */

using IteratorPattern.Core.Enums;
using IteratorPattern.Core.Iterator;
using IteratorPattern.Entities;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Aggregates
{
    /// <summary>
    /// 珠宝业务工序聚合容器(线程安全)
    /// IAggregate 实现,负责维护全部工序数据源
    /// 对外提供多种迭代器创建入口:正向、反向、过滤迭代器
    /// </summary>
    public class JewelleryProcessAggregate : IAggregate<BusinessProcessNode>
    {
        /// <summary>
        /// 读写锁:保障高并发场景下集合读写线程安全
        /// </summary>
        private readonly ReaderWriterLockSlim _rwLock = new ReaderWriterLockSlim();

        /// <summary>
        /// 内部工序存储列表
        /// </summary>
        private readonly List<BusinessProcessNode> _processNodes;

        /// <summary>
        /// 日志对象
        /// </summary>
        private readonly ILogger<JewelleryProcessAggregate> _logger;

        /// <summary>
        /// 构造注入日志,初始化全部业务工序
        /// </summary>
        /// <param name="logger">日志实例</param>
        public JewelleryProcessAggregate(ILogger<JewelleryProcessAggregate> logger)
        {
            _logger = logger;
            _processNodes = new List<BusinessProcessNode>();
            InitializeAllProcessNodes();
        }

        /// <summary>
        /// 初始化所有工序节点,划分链路类型
        /// </summary>
        private void InitializeAllProcessNodes()
        {
            _logger.LogDebug("开始加载珠宝全业务工序定义");

            // ========== 生产链路 ProductionLink ==========
            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 1,
                SortOrder = 1,
                ProcessName = "原料采购核验",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【原料采购核验】贵金属、宝石入库检验,凭证归档");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 2,
                SortOrder = 2,
                ProcessName = "设计制图",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【设计制图】三维建模、首饰图纸确认");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 3,
                SortOrder = 3,
                ProcessName = "加工生产",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【加工生产】起版、倒模、执模、镶石、抛光");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 4,
                SortOrder = 4,
                ProcessName = "质检",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【质检】成色检测、瑕疵检验、证书出具");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 5,
                SortOrder = 5,
                ProcessName = "包装",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【包装】首饰封装、礼盒打包、防盗标签");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 6,
                SortOrder = 6,
                ProcessName = "物流",
                LinkType = BusinessLinkType.ProductionLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【物流】货品出库、保价托运、轨迹跟踪");
                }
            });

            // ========== 职能部门链路 DepartmentLink ==========
            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 7,
                SortOrder = 7,
                ProcessName = "财务",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【财务】成本核算、应收应付、资金对账");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 8,
                SortOrder = 8,
                ProcessName = "营销推广",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【营销推广】活动策划、新品宣传投放");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 9,
                SortOrder = 9,
                ProcessName = "业务",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【业务】客户洽谈、订单跟进、售后维护");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 10,
                SortOrder = 10,
                ProcessName = "人事行政",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【人事行政】招聘、考勤、行政物资管理");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 11,
                SortOrder = 11,
                ProcessName = "IT",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【IT】系统运维、软硬件故障处理");
                }
            });

            _processNodes.Add(new BusinessProcessNode
            {
                ProcessId = 12,
                SortOrder = 12,
                ProcessName = "培训",
                LinkType = BusinessLinkType.DepartmentLink,
                ExecuteAsync = async () =>
                {
                    await Task.Delay(10);
                    _logger.LogInformation("【培训】珠宝工艺、销售专业培训");
                }
            });

            _logger.LogInformation("工序初始化完成,总工序数量:{Count}", _processNodes.Count);
        }

        /// <summary>
        /// IAggregate 标准接口:创建基础正向迭代器
        /// </summary>
        public IIterator<BusinessProcessNode> CreateIterator()
        {
            _rwLock.EnterReadLock();
            try
            {
                var snapshot = _processNodes.ToList().AsReadOnly();
                return new JewelleryProcessIterator(snapshot);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 创建反向迭代器
        /// </summary>
        /// <returns>反向遍历迭代器</returns>
        public IProcessIterator CreateReverseIterator()
        {
            _rwLock.EnterReadLock();
            try
            {
                var snapshot = _processNodes.ToList().AsReadOnly();
                return new ReverseProcessIterator(snapshot);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 创建过滤迭代器(按业务链路筛选)
        /// </summary>
        /// <param name="linkType">链路类型</param>
        /// <returns>过滤后的迭代器</returns>
        public IProcessIterator CreateFilterIterator(BusinessLinkType linkType)
        {
            _rwLock.EnterReadLock();
            try
            {
                var snapshot = _processNodes.ToList();
                return new FilterProcessIterator(snapshot, linkType);
            }
            finally
            {
                _rwLock.ExitReadLock();
            }
        }

        /// <summary>
        /// 释放读写锁资源
        /// </summary>
        public void Dispose()
        {
            _rwLock?.Dispose();
        }
    }
}



/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessLinkType.cs
 
 */
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Enums
{
    /// <summary>
    /// 业务链路类型枚举
    /// 用于过滤迭代器筛选不同业务流程
    /// </summary>
    public enum BusinessLinkType
    {
        /// <summary>
        /// 未指定
        /// </summary>
        None,
        /// <summary>
        /// 生产主链路:原料、设计、加工、质检、包装、物流
        /// </summary>
        ProductionLink,
        /// <summary>
        /// 职能部门链路:财务、营销、人事、IT、培训等
        /// </summary>
        DepartmentLink
    }
}



/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : FilterProcessIterator.cs
 
 */

using IteratorPattern.Core.Enums;
using IteratorPattern.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Iterator
{
    /// <summary>
    /// 过滤条件迭代器
    /// 根据 BusinessLinkType 筛选【生产链路 / 职能部门链路】
    /// 对外保持迭代器统一接口,上层调度器无需修改代码
    /// </summary>
    public class FilterProcessIterator : IProcessIterator
    {
        /// <summary>
        /// 过滤后得到的工序子集
        /// </summary>
        private readonly IReadOnlyList<BusinessProcessNode> _filteredNodes;

        /// <summary>
        /// 当前索引
        /// </summary>
        private int _currentIndex;

        /// <summary>
        /// 构造函数:按链路类型自动过滤工序
        /// </summary>
        /// <param name="sourceNodes">全部原始工序集合</param>
        /// <param name="linkType">需要筛选的链路类型</param>
        public FilterProcessIterator(IEnumerable<BusinessProcessNode> sourceNodes, BusinessLinkType linkType)
        {
            if (sourceNodes == null)
                throw new ArgumentNullException(nameof(sourceNodes));

            _filteredNodes = sourceNodes
                .Where(x => x.LinkType == linkType)
                .OrderBy(x => x.SortOrder)
                .ToList()
                .AsReadOnly();

            _currentIndex = 0;
        }

        public bool HasNext()
        {
            return _currentIndex < _filteredNodes.Count;
        }

        public BusinessProcessNode Next()
        {
            if (!HasNext())
            {
                throw new InvalidOperationException("过滤迭代器已遍历完毕");
            }
            var node = _filteredNodes[_currentIndex];
            _currentIndex++;
            return node;
        }

        public void Reset()
        {
            _currentIndex = 0;
        }
    }
}



/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IAggregate.cs
 
 */

using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Iterator
{
    /// <summary>
    /// 聚合集合抽象接口
    /// Iterator Pattern:提供创建迭代器的入口
    /// </summary>
    /// <typeparam name="T">集合内元素类型</typeparam>
    public interface IAggregate<T>
    {
        /// <summary>
        /// 创建标准正向迭代器
        /// </summary>
        /// <returns>迭代器实例</returns>
        IIterator<T> CreateIterator();
    }
}



/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IIterator.cs
 
 */

using IteratorPattern.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Iterator
{
    /// <summary>
    /// 异步迭代器通用接口
    /// Iterator Pattern 抽象迭代器
    /// </summary>
    /// <typeparam name="T">遍历元素类型</typeparam>
    public interface IIterator<T>
    {
        /// <summary>
        /// 判断是否存在下一个元素
        /// </summary>
        /// <returns>true:存在下一项;false:遍历结束</returns>
        bool HasNext();

        /// <summary>
        /// 获取下一个元素
        /// </summary>
        /// <returns>目标实体对象</returns>
        T Next();

        /// <summary>
        /// 重置迭代指针至起始位置
        /// </summary>
        void Reset();
    }

    /// <summary>
    /// 业务工序专用迭代器别名,简化调用
    /// </summary>
    public interface IProcessIterator : IIterator<BusinessProcessNode>
    {

    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelleryProcessIterator.cs
 
 */

using IteratorPattern.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Iterator
{
    /// <summary>
    /// 基础正向工序迭代器
    /// 从头到尾顺序遍历全部工序节点
    /// 多线程并发遍历只读安全
    /// </summary>
    public class JewelleryProcessIterator : IProcessIterator
    {
        /// <summary>
        /// 原始只读工序集合
        /// </summary>
        private readonly IReadOnlyList<BusinessProcessNode> _sourceNodes;

        /// <summary>
        /// 当前遍历索引
        /// </summary>
        private int _currentIndex;

        /// <summary>
        /// 构造函数注入只读工序集合
        /// </summary>
        /// <param name="sourceNodes">工序只读列表</param>
        public JewelleryProcessIterator(IReadOnlyList<BusinessProcessNode> sourceNodes)
        {
            _sourceNodes = sourceNodes ?? throw new ArgumentNullException(nameof(sourceNodes));
            _currentIndex = 0;
        }

        /// <summary>
        /// 判断是否存在下一个工序
        /// </summary>
        public bool HasNext()
        {
            return _currentIndex < _sourceNodes.Count;
        }

        /// <summary>
        /// 获取下一个工序节点
        /// </summary>
        public BusinessProcessNode Next()
        {
            if (!HasNext())
            {
                throw new InvalidOperationException("迭代器已到达集合末尾,无更多元素");
            }
            var item = _sourceNodes[_currentIndex];
            _currentIndex++;
            return item;
        }

        /// <summary>
        /// 重置索引指针回到起点
        /// </summary>
        public void Reset()
        {
            _currentIndex = 0;
        }
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : ReverseProcessIterator.cs
 
 */
using IteratorPattern.Entities;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Core.Iterator
{
    /// <summary>
    /// 反向工序迭代器
    /// 从最后一项向前倒序遍历
    /// </summary>
    public class ReverseProcessIterator : IProcessIterator
    {
        /// <summary>
        /// 原始只读工序集合
        /// </summary>
        private readonly IReadOnlyList<BusinessProcessNode> _sourceNodes;

        /// <summary>
        /// 当前遍历索引
        /// </summary>
        private int _currentIndex;

        /// <summary>
        /// 构造反向迭代器
        /// </summary>
        /// <param name="sourceNodes">工序只读集合</param>
        public ReverseProcessIterator(IReadOnlyList<BusinessProcessNode> sourceNodes)
        {
            _sourceNodes = sourceNodes ?? throw new ArgumentNullException(nameof(sourceNodes));
            _currentIndex = sourceNodes.Count - 1;
        }

        public bool HasNext()
        {
            return _currentIndex >= 0;
        }

        public BusinessProcessNode Next()
        {
            if (!HasNext())
            {
                throw new InvalidOperationException("反向迭代器遍历完成,不存在下一项");
            }
            var node = _sourceNodes[_currentIndex];
            _currentIndex--;
            return node;
        }

        public void Reset()
        {
            _currentIndex = _sourceNodes.Count - 1;
        }
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessProcessNode.cs
 
 */

using IteratorPattern.Core.Enums;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Entities
{
    /// <summary>
    /// 珠宝业务工序节点实体
    /// 存储工序基础信息与异步执行委托
    /// </summary>
    public class BusinessProcessNode
    {
        /// <summary>
        /// 工序唯一ID
        /// </summary>
        public int ProcessId { get; set; }

        /// <summary>
        /// 工序名称
        /// </summary>
        public string ProcessName { get; set; } = string.Empty;

        /// <summary>
        /// 全局执行顺序号
        /// </summary>
        public int SortOrder { get; set; }

        /// <summary>
        /// 当前工序归属链路类型
        /// </summary>
        public BusinessLinkType LinkType { get; set; }

        /// <summary>
        /// 异步工序执行逻辑委托
        /// </summary>
        public Func<Task> ExecuteAsync { get; set; } = async () => await Task.CompletedTask;
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : LogConfigSwitch.cs
 
 */
using Karambolo.Extensions.Logging.File;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.IO;

namespace IteratorPattern.Infrastructure.Logging
{
    /// <summary>
    /// 日志配置切换工具
    /// 模式1:普通文本日志(原有格式,控制台与文件保持一致)
    /// 模式2:Json结构化日志(用于日志收集平台)
    /// </summary>
    public static class LogConfigSwitch
    {
        /// <summary>
        /// 是否启用Json结构化日志
        /// true=Json格式;false=普通文本模板
        /// 修改此处一键切换
        /// </summary>
        public const bool EnableJsonStructuredLog = false;

        /// <summary>
        /// 配置文件日志(使用 Karambolo 4.x API)
        /// </summary>
        public static void ConfigureFileLogger(ILoggingBuilder loggingBuilder)
        {
            string todayDate = DateTime.Now.ToString("yyyy-MM-dd");
            string logRootPath = Path.Combine(Directory.GetCurrentDirectory(), "Logs");

            loggingBuilder.AddFile(fileBuilder =>
            {
                fileBuilder.RootPath = logRootPath;
                fileBuilder.Files = new[]
                {
                    new LogFileOptions 
                    { 
                        Path = $"{todayDate}/app-debug.log", 
                        MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Debug },
                        MaxFileSize = 100 * 1024 * 1024
                    },
                    new LogFileOptions 
                    { 
                        Path = $"{todayDate}/app-info.log", 
                        MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Information },
                        MaxFileSize = 100 * 1024 * 1024
                    },
                    new LogFileOptions 
                    { 
                        Path = $"{todayDate}/app-warn.log", 
                        MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Warning },
                        MaxFileSize = 100 * 1024 * 1024
                    },
                    new LogFileOptions 
                    { 
                        Path = $"{todayDate}/app-error.log", 
                        MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Error },
                        MaxFileSize = 100 * 1024 * 1024
                    }
                };
            });
        }
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : RetryHelper.cs
 
 */

using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Infrastructure.Resilience
{
    /// <summary>
    /// 通用异步重试帮助类
    /// 用于珠宝业务工序、定时任务异常自动重试
    /// </summary>
    public class RetryHelper
    {
        /// <summary>
        /// 日志对象
        /// </summary>
        private readonly ILogger<RetryHelper> _logger;

        /// <summary>
        /// 构造注入日志
        /// </summary>
        /// <param name="logger">日志实例</param>
        public RetryHelper(ILogger<RetryHelper> logger)
        {
            _logger = logger;
        }

        /// <summary>
        /// 执行异步任务,失败自动重试
        /// </summary>
        /// <param name="action">待执行异步业务方法</param>
        /// <param name="maxRetryTimes">最大重试次数</param>
        /// <param name="delayMs">每次重试间隔(毫秒)</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <param name="skipExceptions">不需要重试的异常类型集合</param>
        /// <returns>是否最终执行成功</returns>
        public async Task<bool> ExecuteWithRetryAsync(
            Func<Task> action,
            int maxRetryTimes = 3,
            int delayMs = 2000,
            CancellationToken cancellationToken = default,
            HashSet<Type>? skipExceptions = null)
        {
            if (action == null)
                throw new ArgumentNullException(nameof(action));

            int currentRetry = 0;
            while (true)
            {
                try
                {
                    await action.Invoke();
                    if (currentRetry > 0)
                    {
                        _logger.LogInformation("业务执行成功!经过{RetryTimes}次重试", currentRetry);
                    }
                    return true;
                }
                catch (Exception ex)
                {
                    // 如果属于跳过异常,直接抛出不重试
                    if (skipExceptions != null && skipExceptions.Contains(ex.GetType()))
                    {
                        _logger.LogError(ex, "捕获到无需重试的异常,终止执行");
                        throw;
                    }

                    currentRetry++;
                    if (currentRetry > maxRetryTimes)
                    {
                        _logger.LogError(ex, "已达到最大重试次数{MaxRetry},任务执行失败", maxRetryTimes);
                        return false;
                    }

                    _logger.LogWarning(ex, "业务执行异常,准备第{CurrentRetry}/{MaxRetry}次重试,等待{Delay}ms",
                        currentRetry, maxRetryTimes, delayMs);

                    await Task.Delay(delayMs, cancellationToken);
                }
            }
        }
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelleryProcessJob.cs
 
 */

using IteratorPattern.Core.Enums;
using IteratorPattern.Infrastructure.Resilience;
using IteratorPattern.Schedulers;
using Microsoft.Extensions.Logging;
using Quartz;
using System;
using System.Collections.Generic;

namespace IteratorPattern.Infrastructure.Tasks
{
    /// <summary>
    /// Quartz定时任务:珠宝业务流程执行Job
    /// 支持配置执行链路:全流程/生产链路/职能部门链路
    /// 内置异常重试策略
    /// </summary>
    [DisallowConcurrentExecution] // 禁止同一个任务并发执行,防止业务重复跑
    public class JewelleryProcessJob : IJob
    {
        /// <summary>
        /// 业务流程调度器
        /// </summary>
        private readonly BusinessProcessScheduler _processScheduler;

        /// <summary>
        /// 重试工具类
        /// </summary>
        private readonly RetryHelper _retryHelper;

        /// <summary>
        /// 日志
        /// </summary>
        private readonly ILogger<JewelleryProcessJob> _logger;

        /// <summary>
        /// DI构造注入依赖
        /// </summary>
        public JewelleryProcessJob(
            BusinessProcessScheduler processScheduler,
            RetryHelper retryHelper,
            ILogger<JewelleryProcessJob> logger)
        {
            _processScheduler = processScheduler;
            _retryHelper = retryHelper;
            _logger = logger;
        }

        /// <summary>
        /// Quartz任务执行入口
        /// </summary>
        /// <param name="context">任务执行上下文</param>
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                _logger.LogInformation("Quartz定时任务启动,任务Key:{JobKey}", context.JobDetail.Key);

                // 从JobDataMap读取配置参数,灵活指定执行链路
                var linkTypeStr = context.MergedJobDataMap.GetString("TargetLinkType");
                Enum.TryParse(linkTypeStr, out BusinessLinkType targetLink);

                bool executeResult;
                if (targetLink == BusinessLinkType.None)
                {
                    // 执行全部工序链路
                    executeResult = await _retryHelper.ExecuteWithRetryAsync(
                        () => _processScheduler.RunFullAllProcessAsync(context.CancellationToken),
                        maxRetryTimes: 3,
                        delayMs: 3000,
                        cancellationToken: context.CancellationToken);
                }
                else
                {
                    // 执行指定过滤链路(生产/职能部门)
                    executeResult = await _retryHelper.ExecuteWithRetryAsync(
                        () => _processScheduler.RunFilterLinkAsync(targetLink, context.CancellationToken),
                        maxRetryTimes: 3,
                        delayMs: 3000,
                        cancellationToken: context.CancellationToken);
                }

                if (!executeResult)
                {
                    // 多次重试仍然失败,可以扩展:短信/邮件告警
                    _logger.LogCritical("定时业务任务最终执行失败,请人工核查!");
                }
                else
                {
                    _logger.LogInformation("Quartz定时任务正常执行完成,任务Key:{JobKey}", context.JobDetail.Key);
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Quartz Job 顶层捕获未处理异常,任务中断");
            }
        }
    }
}


/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessProcessScheduler.cs
 
 */

using IteratorPattern.Aggregates;
using IteratorPattern.Core.Enums;
using IteratorPattern.Core.Iterator;
using IteratorPattern.Entities;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Text;

namespace IteratorPattern.Schedulers
{
    /// <summary>
    /// 珠宝业务流程异步调度器
    /// 使用各类迭代器驱动不同业务链路执行
    /// 全部逻辑异步实现,支持取消令牌
    /// </summary>
    public class BusinessProcessScheduler
    {
        /// <summary>
        /// 日志实例
        /// </summary>
        private readonly ILogger<BusinessProcessScheduler> _logger;

        /// <summary>
        /// 工序聚合数据源
        /// </summary>
        private readonly JewelleryProcessAggregate _processAggregate;

        /// <summary>
        /// DI构造注入依赖
        /// </summary>
        /// <param name="logger">日志</param>
        /// <param name="aggregate">工序聚合容器</param>
        public BusinessProcessScheduler(ILogger<BusinessProcessScheduler> logger, JewelleryProcessAggregate aggregate)
        {
            _logger = logger;
            _processAggregate = aggregate;
        }

        /// <summary>
        /// 执行全链路正向遍历(所有工序)
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task RunFullAllProcessAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogInformation("==========【开始执行全部业务工序正向流程】==========");
                IProcessIterator iterator = (IProcessIterator)_processAggregate.CreateIterator();

                while (iterator.HasNext() && !cancellationToken.IsCancellationRequested)
                {
                    BusinessProcessNode node = iterator.Next();
                    _logger.LogDebug("开始执行工序:{ProcessName} | 链路:{LinkType}", node.ProcessName, node.LinkType);
                    await node.ExecuteAsync();
                }

                _logger.LogInformation("==========【全部业务工序正向流程执行完毕】==========");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "执行全业务流程发生异常");
            }
        }

        /// <summary>
        /// 执行指定链路过滤流程
        /// </summary>
        /// <param name="linkType">链路类型</param>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task RunFilterLinkAsync(BusinessLinkType linkType, CancellationToken cancellationToken = default)
        {
            try
            {
                string linkName = linkType == BusinessLinkType.ProductionLink ? "生产主链路" : "职能部门链路";
                _logger.LogInformation($"==========【开始执行{linkName}】==========");

                IProcessIterator iterator = _processAggregate.CreateFilterIterator(linkType);
                if (!iterator.HasNext())
                {
                    _logger.LogWarning("{LinkName}未匹配到任何工序", linkName);
                    return;
                }

                while (iterator.HasNext() && !cancellationToken.IsCancellationRequested)
                {
                    BusinessProcessNode node = iterator.Next();
                    _logger.LogDebug("执行工序:{ProcessName}", node.ProcessName);
                    await node.ExecuteAsync();
                }

                _logger.LogInformation($"==========【{linkName}执行完成】==========");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "过滤链路执行异常,链路类型:{LinkType}", linkType);
            }
        }

        /// <summary>
        /// 反向遍历所有工序(演示反向迭代器)
        /// </summary>
        /// <param name="cancellationToken">取消令牌</param>
        public async Task RunReverseAllProcessAsync(CancellationToken cancellationToken = default)
        {
            try
            {
                _logger.LogWarning("==========【启动工序反向遍历流程(测试)】==========");
                IProcessIterator iterator = _processAggregate.CreateReverseIterator();

                while (iterator.HasNext() && !cancellationToken.IsCancellationRequested)
                {
                    BusinessProcessNode node = iterator.Next();
                    _logger.LogDebug("反向遍历工序:{ProcessName}", node.ProcessName);
                    await node.ExecuteAsync();
                }
                _logger.LogInformation("==========【工序反向遍历流程结束】==========");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "反向遍历流程异常");
            }
        }
    }
}

  

调用:

/*
 # encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:行为模式 Behavioral Patterns 迭代器模式 Iterator Pattern演示业务层
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : vs2026 c# .net 10
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/07/25 20:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IteratorBll.cs
 
 */
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;
using IteratorPattern.Aggregates;
using IteratorPattern.Core.Enums;
using IteratorPattern.Infrastructure.Logging;
using IteratorPattern.Infrastructure.Resilience;
using IteratorPattern.Infrastructure.Tasks;
using IteratorPattern.Schedulers;
using Karambolo.Extensions.Logging.File;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Quartz;

namespace BLL
{
    /// <summary>
    /// 迭代器模式业务演示
    /// </summary>
    public class IteratorBll
    {
        /// <summary>
        /// 演示迭代器模式
        /// </summary>
        public async Task Demo()
        {
            Console.WriteLine("=====迭代器模式演示启动=====\n");

            #region 第一部分:基础演示
            Console.WriteLine("【第一部分】基础演示 - 全工序执行");
            Console.WriteLine("----------------------------------------");

            var host = Host.CreateDefaultBuilder(Array.Empty<string>())
                .ConfigureLogging((ctx, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddConsole();

                    // 文件日志配置 Karambolo 4.x
                    string todayDate = DateTime.Now.ToString("yyyy-MM-dd");
                    string logRootPath = Path.Combine(Directory.GetCurrentDirectory(), "Logs");
                    loggingBuilder.AddFile(fileBuilder =>
                    {
                        fileBuilder.RootPath = logRootPath;
                        fileBuilder.Files = new[]
                        {
                            new LogFileOptions { Path = $"{todayDate}/app-debug.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Debug }, MaxFileSize = 100 * 1024 * 1024 },
                            new LogFileOptions { Path = $"{todayDate}/app-info.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Information }, MaxFileSize = 100 * 1024 * 1024 },
                            new LogFileOptions { Path = $"{todayDate}/app-warn.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Warning }, MaxFileSize = 100 * 1024 * 1024 },
                            new LogFileOptions { Path = $"{todayDate}/app-error.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Error }, MaxFileSize = 100 * 1024 * 1024 }
                        };
                    });

                    loggingBuilder.SetMinimumLevel(LogLevel.Debug);
                })
                .ConfigureServices((ctx, services) =>
                {
                    services.AddScoped<JewelleryProcessAggregate>();
                    services.AddScoped<BusinessProcessScheduler>();
                })
                .Build();

            using (var scope = host.Services.CreateScope())
            {
                var scheduler = scope.ServiceProvider.GetRequiredService<BusinessProcessScheduler>();
                var logger = scope.ServiceProvider.GetRequiredService<ILogger<IteratorBll>>();

                logger.LogInformation("开始执行全工序正向流程");
                Console.WriteLine("1. 完整全工序正向执行:");
                await scheduler.RunFullAllProcessAsync();
                Console.WriteLine();

                logger.LogInformation("开始执行生产链路过滤");
                Console.WriteLine("2. 单独执行【生产链路】:");
                await scheduler.RunFilterLinkAsync(BusinessLinkType.ProductionLink);
                Console.WriteLine();

                logger.LogInformation("开始执行职能部门链路过滤");
                Console.WriteLine("3. 单独执行【职能部门链路】:");
                await scheduler.RunFilterLinkAsync(BusinessLinkType.DepartmentLink);
                Console.WriteLine();

                logger.LogInformation("开始执行反向遍历");
                Console.WriteLine("4. 反向遍历测试:");
                await scheduler.RunReverseAllProcessAsync();
            }

            await host.StopAsync();
            host.Dispose();
            Console.WriteLine("第一部分执行完成\n");
            #endregion

            #region 第二部分:Quartz定时任务演示
            Console.WriteLine("【第二部分】Quartz定时任务演示");
            Console.WriteLine("----------------------------------------");

            var host2 = Host.CreateDefaultBuilder(Array.Empty<string>())
                .ConfigureLogging((ctx, loggingBuilder) =>
                {
                    loggingBuilder.ClearProviders();
                    loggingBuilder.AddConsole();

                    // 使用统一日志配置
                    LogConfigSwitch.ConfigureFileLogger(loggingBuilder);

                    loggingBuilder.SetMinimumLevel(LogLevel.Debug);
                })
                .ConfigureServices((ctx, services) =>
                {
                    services.AddScoped<JewelleryProcessAggregate>();
                    services.AddScoped<BusinessProcessScheduler>();
                    services.AddScoped<RetryHelper>();

                    // ========== Quartz 定时任务注册 ==========
                    services.AddQuartz(q =>
                    {
                        q.AddJob<JewelleryProcessJob>(opts => opts.WithIdentity("JewelleryProcessJob"));

                        // 触发器1:每天凌晨02:00 执行【完整全业务链路】
                        q.AddTrigger(opts => opts
                            .ForJob("JewelleryProcessJob")
                            .WithIdentity("Trigger_FullProcess")
                            .WithCronSchedule("0 0 2 * * ?")
                            .UsingJobData("TargetLinkType", nameof(BusinessLinkType.None)));

                        // 触发器2:每天上午09:30 执行【生产链路】
                        q.AddTrigger(opts => opts
                            .ForJob("JewelleryProcessJob")
                            .WithIdentity("Trigger_ProductionLink")
                            .WithCronSchedule("0 30 9 * * ?")
                            .UsingJobData("TargetLinkType", nameof(BusinessLinkType.ProductionLink)));

                        // 触发器3:每周一 10:00 执行【职能部门链路】
                        q.AddTrigger(opts => opts
                            .ForJob("JewelleryProcessJob")
                            .WithIdentity("Trigger_DepartmentLink")
                            .WithCronSchedule("0 0 10 ? * MON")
                            .UsingJobData("TargetLinkType", nameof(BusinessLinkType.DepartmentLink)));
                    });

                    services.AddQuartzHostedService(opt =>
                    {
                        opt.WaitForJobsToComplete = false;
                    });
                })
                .Build();

            // 演示同步手动执行
            using (var scope2 = host2.Services.CreateScope())
            {
                var scheduler = scope2.ServiceProvider.GetRequiredService<BusinessProcessScheduler>();
                var logger = scope2.ServiceProvider.GetRequiredService<ILogger<IteratorBll>>();

                logger.LogInformation("手动执行全工序流程");
                Console.WriteLine("手动执行全工序流程:");
                await scheduler.RunFullAllProcessAsync();
                Console.WriteLine();

                logger.LogInformation("手动执行生产链路");
                Console.WriteLine("手动执行生产链路:");
                await scheduler.RunFilterLinkAsync(BusinessLinkType.ProductionLink);
            }

            Console.WriteLine();
            Console.WriteLine("==============================");
            Console.WriteLine("程序启动完成,Quartz定时调度器已运行");
            Console.WriteLine("按任意键退出程序");
            Console.WriteLine("==============================");

            Console.ReadKey();
            await host2.StopAsync();
            #endregion
        }
    }
}

 

输出:

image

 

posted @ 2026-08-02 07:02  ®Geovin Du Dream Park™  阅读(7)  评论(0)    收藏  举报