CSharp:Proxy Pattern

项目结构:

image

 

/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IJewelryBusinessService.cs
 */

using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Domain.Abstractions
{
    /// <summary>
    /// 珠宝业务统一服务抽象主题(Subject)
    /// 所有业务模块实现该接口,由代理统一拦截
    /// </summary>
    public interface IJewelryBusinessService
    {
        /// <summary>
        /// 获取业务模块名称
        /// </summary>
        string GetModuleName();

        /// <summary>
        /// 获取当前模块所需权限编码
        /// </summary>
        string GetRequiredPermissionCode();

        /// <summary>
        /// 执行业务逻辑
        /// </summary>
        /// <param name="context">业务上下文</param>
        /// <param name="businessOrderNo">业务单号</param>
        /// <param name="businessParam">业务入参</param>
        /// <returns>业务执行结果</returns>
        Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam);
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessAuditRecord.cs
 */

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

namespace ProxyPattern.Domain.Models
{
    /// <summary>
    /// 业务操作审计记录实体
    /// </summary>
    public class BusinessAuditRecord
    {
        /// <summary>
        /// 审计主键
        /// </summary>
        public long Id { get; set; }

        /// <summary>
        /// 追踪ID
        /// </summary>
        public string TraceId { get; set; } = string.Empty;

        /// <summary>
        /// 业务单号
        /// </summary>
        public string BusinessOrderNo { get; set; } = string.Empty;

        /// <summary>
        /// 业务模块名称
        /// </summary>
        public string ModuleName { get; set; } = string.Empty;

        /// <summary>
        /// 操作员编号
        /// </summary>
        public string OperatorId { get; set; } = string.Empty;

        /// <summary>
        /// 操作员名称
        /// </summary>
        public string OperatorName { get; set; } = string.Empty;

        /// <summary>
        /// 入参JSON
        /// </summary>
        public string InputParamJson { get; set; } = string.Empty;

        /// <summary>
        /// 返回结果JSON
        /// </summary>
        public string ResultJson { get; set; } = string.Empty;

        /// <summary>
        /// 执行耗时(ms)
        /// </summary>
        public long ElapsedMs { get; set; }

        /// <summary>
        /// 是否执行成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 异常信息
        /// </summary>
        public string? ExceptionMessage { get; set; }

        /// <summary>
        /// 创建时间
        /// </summary>
        public DateTime CreateTime { get; set; }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessContext.cs
 */

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

namespace ProxyPattern.Domain.Models
{
    /// <summary>
    /// 业务执行上下文
    /// 携带操作员、租户、权限标识,供代理层权限校验、审计使用
    /// </summary>
    public class BusinessContext
    {
        /// <summary>
        /// 当前操作人编号
        /// </summary>
        public string OperatorId { get; set; } = string.Empty;

        /// <summary>
        /// 操作员名称
        /// </summary>
        public string OperatorName { get; set; } = string.Empty;

        /// <summary>
        /// 租户编号
        /// </summary>
        public string TenantId { get; set; } = string.Empty;

        /// <summary>
        /// 请求唯一追踪ID,用于全链路追踪
        /// </summary>
        public string TraceId { get; set; } = Guid.NewGuid().ToString("N");

        /// <summary>
        /// 当前请求拥有的权限编码集合
        /// </summary>
        public HashSet<string> PermissionCodes { get; set; } = new HashSet<string>();
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryBusinessResult.cs
 */

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

namespace ProxyPattern.Domain.Models
{
    /// <summary>
    /// 珠宝业务统一返回模型
    /// </summary>
    public class JewelryBusinessResult
    {
        /// <summary>
        /// 是否执行成功
        /// </summary>
        public bool Success { get; set; }

        /// <summary>
        /// 返回消息
        /// </summary>
        public string Message { get; set; } = string.Empty;

        /// <summary>
        /// 业务自定义数据
        /// </summary>
        public object? Data { get; set; }

        /// <summary>
        /// 创建成功返回结果
        /// </summary>
        public static JewelryBusinessResult Ok(string msg, object? data = null)
        {
            return new JewelryBusinessResult
            {
                Success = true,
                Message = msg,
                Data = data
            };
        }

        /// <summary>
        /// 创建失败返回结果
        /// </summary>
        public static JewelryBusinessResult Fail(string msg, object? data = null)
        {
            return new JewelryBusinessResult
            {
                Success = false,
                Message = msg,
                Data = data
            };
        }
    }
}



/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IAuditRepository.cs
 */

using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Infrastructure.Audit
{
    /// <summary>
    /// 审计仓储接口,支持切换内存/数据库持久化
    /// </summary>
    public interface IAuditRepository
    {
        /// <summary>
        /// 异步保存审计记录
        /// </summary>
        Task SaveAuditRecordAsync(BusinessAuditRecord record);
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : MemoryAuditRepository.cs
 */

using ProxyPattern.Domain.Models;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Infrastructure.Audit
{
    /// <summary>
    /// 内存审计仓储实现(线程安全)
    /// 生产环境替换为SqlAuditRepository写入数据库
    /// </summary>
    public class MemoryAuditRepository : IAuditRepository
    {
        private readonly ConcurrentQueue<BusinessAuditRecord> _auditQueue = new();

        public async Task SaveAuditRecordAsync(BusinessAuditRecord record)
        {
            // 模拟异步IO,真实场景替换为数据库写入
            await Task.Yield();
            _auditQueue.Enqueue(record);
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : HangfireTaskScheduler.cs
 */

using Hangfire;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Models;
using ProxyPattern.Domain.Abstractions;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Infrastructure.Hangfire
{
    /// <summary>
    /// Hangfire统一任务调度封装
    /// 支持一次性任务、延迟任务、循环定时任务
    /// </summary>
    public class HangfireTaskScheduler
    {
        private readonly IServiceScopeFactory _scopeFactory;
        private readonly ILogger<HangfireTaskScheduler> _logger;
        private readonly IBackgroundJobClient _backgroundJobClient;
        private readonly IRecurringJobManager _recurringJobManager;

        public HangfireTaskScheduler(IServiceScopeFactory scopeFactory, ILogger<HangfireTaskScheduler> logger, 
            IBackgroundJobClient backgroundJobClient, IRecurringJobManager recurringJobManager)
        {
            _scopeFactory = scopeFactory;
            _logger = logger;
            _backgroundJobClient = backgroundJobClient;
            _recurringJobManager = recurringJobManager;
        }

        /// <summary>
        /// 调度单次执行业务流程任务
        /// </summary>
        /// <param name="context">业务上下文</param>
        /// <param name="orderNo">业务单号</param>
        /// <param name="param">业务参数</param>
        public string EnqueueBusinessTask(BusinessContext context, string orderNo, Dictionary<string, object> param)
        {
            string jobId = _backgroundJobClient.Enqueue(() => ExecuteBusinessJob(context, orderNo, param));
            _logger.LogInformation("Hangfire一次性任务已入队 JobId:{JobId},OrderNo:{OrderNo}", jobId, orderNo);
            return jobId;
        }

        /// <summary>
        /// 延迟执行任务
        /// </summary>
        public string ScheduleBusinessTask(BusinessContext context, string orderNo, Dictionary<string, object> param, TimeSpan delay)
        {
            string jobId = _backgroundJobClient.Schedule(() => ExecuteBusinessJob(context, orderNo, param), delay);
            _logger.LogInformation("Hangfire延迟任务已创建 JobId:{JobId},Delay:{Delay}", jobId, delay);
            return jobId;
        }

        /// <summary>
        /// 循环定时任务(Cron表达式)
        /// </summary>
        public void RecurringBusinessTask(string recurringJobId, string cron, BusinessContext context, string orderNo, Dictionary<string, object> param)
        {
            _recurringJobManager.AddOrUpdate(recurringJobId, () => ExecuteBusinessJob(context, orderNo, param), cron);
            _logger.LogInformation("Hangfire循环任务注册完成 RecurringId:{RecurringId},Cron:{Cron}", recurringJobId, cron);
        }

        /// <summary>
        /// Hangfire执行入口(必须public,序列化调用)
        /// </summary>
        public async Task ExecuteBusinessJob(BusinessContext context, string orderNo, Dictionary<string, object> param)
        {
            using var scope = _scopeFactory.CreateScope();
            var scheduler = scope.ServiceProvider.GetRequiredService<Scheduler.JewelryBusinessFlowScheduler>();
            await scheduler.RunFullBusinessFlowAsync(context, orderNo, param);
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : LogCleanBackgroundService.cs
 */

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

namespace ProxyPattern.Infrastructure.Logging
{
    /// <summary>
    /// 日志自动清理后台服务
    /// 定时扫描Logs目录,删除超过保留天数的日期文件夹,线程安全
    /// </summary>
    public class LogCleanBackgroundService : BackgroundService
    {
        private readonly ILogger<LogCleanBackgroundService> _logger;
        private readonly string _logBasePath;
        private readonly int _retainDays;
        private readonly TimeSpan _scanInterval;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="logger">日志器</param>
        /// <param name="logBasePath">日志根目录</param>
        /// <param name="retainDays">日志保留天数</param>
        /// <param name="scanInterval">扫描周期</param>
        public LogCleanBackgroundService(ILogger<LogCleanBackgroundService> logger,
            string logBasePath,
            int retainDays = 30,
            TimeSpan? scanInterval = null)
        {
            _logger = logger;
            _logBasePath = Path.GetFullPath(logBasePath);
            _retainDays = retainDays;
            _scanInterval = scanInterval ?? TimeSpan.FromHours(6);
            Directory.CreateDirectory(_logBasePath);
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("日志清理后台服务启动,日志保留天数:{Days},扫描间隔:{Interval}",
                _retainDays, _scanInterval);

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    CleanExpiredLogs();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "执行过期日志清理发生异常");
                }
                await Task.Delay(_scanInterval, stoppingToken);
            }
            _logger.LogInformation("日志清理后台服务停止");
        }

        /// <summary>
        /// 执行清理逻辑
        /// </summary>
        private void CleanExpiredLogs()
        {
            var cutoffDate = DateTime.Now.AddDays(-_retainDays);
            var dirs = Directory.GetDirectories(_logBasePath);

            foreach (var dir in dirs)
            {
                var dirName = Path.GetFileName(dir);
                if (!DateTime.TryParseExact(dirName, "yyyy-MM-dd", null,
                        System.Globalization.DateTimeStyles.None, out var folderDate))
                {
                    continue;
                }
                if (folderDate < cutoffDate)
                {
                    try
                    {
                        Directory.Delete(dir, true);
                        _logger.LogInformation("已删除过期日志目录:{Dir}", dir);
                    }
                    catch (Exception ex)
                    {
                        _logger.LogWarning(ex, "删除日志目录失败 {Dir}", dir);
                    }
                }
            }
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : StructuredLogFormatter.cs
 */

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


namespace ProxyPattern.Infrastructure.Logging
{
    /// <summary>
    /// 结构化JSON日志格式化器
    /// 同时支持普通文本日志输出,保证控制台与文件日志格式对齐
    /// </summary>
    public static class StructuredLogFormatter
    {
        private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
        {
            WriteIndented = false,
            Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };

        /// <summary>
        /// 生成文本格式日志(控制台、普通文件日志共用)
        /// </summary>
        public static string FormatPlainText(LogEntry<string> logEntry, Exception? ex)
        {
            string baseText = $"[{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff}] [{logEntry.LogLevel}] {logEntry.Category} > {logEntry.State}";
            if (ex != null)
            {
                baseText += Environment.NewLine + ex.ToString();
            }
            return baseText;
        }

        /// <summary>
        /// 生成结构化JSON日志字符串
        /// </summary>
        public static string FormatJson(LogEntry<string> logEntry, Exception? ex)
        {
            var logObj = new
            {
                Timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"),
                Level = logEntry.LogLevel.ToString(),
                Category = logEntry.Category,
                Message = logEntry.State,
                Exception = ex?.ToString()
            };
            return JsonSerializer.Serialize(logObj, _jsonOptions);
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : ConcurrentRateLimiter.cs
 */

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

namespace ProxyPattern.Infrastructure.RateLimit
{
    /// <summary>
    /// 基于并发字典的简易滑动窗口限流(线程安全)
    /// 企业级可替换为Redis分布式限流
    /// </summary>
    public class ConcurrentRateLimiter : IRateLimiter
    {
        /// <summary>
        /// 单模块最大并发数量
        /// </summary>
        private readonly int _maxConcurrent;

        private readonly ConcurrentDictionary<string, int> _concurrentCounter = new();

        public ConcurrentRateLimiter(int maxConcurrent = 20)
        {
            _maxConcurrent = maxConcurrent;
        }

        public bool IsLimited(string moduleKey)
        {
            int current = _concurrentCounter.GetOrAdd(moduleKey, 0);
            if (current >= _maxConcurrent)
            {
                return true;
            }
            _concurrentCounter.AddOrUpdate(moduleKey, 1, (k, v) => v + 1);
            return false;
        }

        /// <summary>
        /// 释放占用计数(业务执行完成后调用)
        /// </summary>
        public void Release(string moduleKey)
        {
            _concurrentCounter.AddOrUpdate(moduleKey, 0, (k, v) => Math.Max(0, v - 1));
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IRateLimiter.cs
 */

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

namespace ProxyPattern.Infrastructure.RateLimit
{
    /// <summary>
    /// 限流校验器接口
    /// </summary>
    public interface IRateLimiter
    {
        /// <summary>
        /// 判断当前模块是否触发限流
        /// </summary>
        /// <param name="moduleKey">模块标识</param>
        /// <returns>true=触发限流,false=允许通行</returns>
        bool IsLimited(string moduleKey);
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : IPermissionChecker.cs
 */

using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Infrastructure.Security
{
    /// <summary>
    /// 权限校验接口
    /// </summary>
    public interface IPermissionChecker
    {
        /// <summary>
        /// 校验上下文是否拥有指定权限
        /// </summary>
        bool CheckPermission(BusinessContext context, string requiredPermissionCode);
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryPermissionChecker.cs
 */

using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Infrastructure.Security
{
    /// <summary>
    /// 珠宝业务权限校验实现
    /// </summary>
    public class JewelryPermissionChecker : IPermissionChecker
    {
        public bool CheckPermission(BusinessContext context, string requiredPermissionCode)
        {
            if (string.IsNullOrEmpty(requiredPermissionCode))
                return true;
            return context.PermissionCodes.Contains(requiredPermissionCode);
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryBusinessServiceProxy.cs
 */

using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using ProxyPattern.Infrastructure.Audit;
using ProxyPattern.Infrastructure.RateLimit;
using ProxyPattern.Infrastructure.Security;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text.Encodings.Web;
using System.Text.Json;

namespace ProxyPattern.Proxy
{
    /// <summary>
    /// 珠宝业务增强代理(Proxy Pattern)
    /// 横切拦截顺序:限流 → 权限校验 → 执行业务 → 日志记录 → 审计入库 → 异常捕获
    /// </summary>
    /// <typeparam name="TRealService">真实业务实现类</typeparam>
    public class JewelryBusinessServiceProxy<TRealService> : IJewelryBusinessService
        where TRealService : class, IJewelryBusinessService
    {
        private static readonly JsonSerializerOptions _jsonOptions = new JsonSerializerOptions
        {
            Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping
        };

        private readonly TRealService _realService;
        private readonly ILogger<JewelryBusinessServiceProxy<TRealService>> _logger;
        private readonly IPermissionChecker _permissionChecker;
        private readonly IRateLimiter _rateLimiter;
        private readonly IAuditRepository _auditRepository;
        private readonly ConcurrentRateLimiter _concurrentRateLimiter;

        public JewelryBusinessServiceProxy(TRealService realService,
            ILogger<JewelryBusinessServiceProxy<TRealService>> logger,
            IPermissionChecker permissionChecker,
            IRateLimiter rateLimiter,
            IAuditRepository auditRepository,
            ConcurrentRateLimiter concurrentRateLimiter)
        {
            _realService = realService;
            _logger = logger;
            _permissionChecker = permissionChecker;
            _rateLimiter = rateLimiter;
            _auditRepository = auditRepository;
            _concurrentRateLimiter = concurrentRateLimiter;
        }

        public string GetModuleName()
        {
            return _realService.GetModuleName();
        }

        public string GetRequiredPermissionCode()
        {
            return _realService.GetRequiredPermissionCode();
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            string moduleName = GetModuleName();
            string permissionCode = GetRequiredPermissionCode();
            string auditTraceId = context.TraceId;
            Stopwatch stopwatch = Stopwatch.StartNew();
            BusinessAuditRecord auditRecord = new BusinessAuditRecord
            {
                TraceId = auditTraceId,
                BusinessOrderNo = businessOrderNo,
                ModuleName = moduleName,
                OperatorId = context.OperatorId,
                OperatorName = context.OperatorName,
                InputParamJson = JsonSerializer.Serialize(businessParam, _jsonOptions),
                CreateTime = DateTime.Now
            };

            try
            {
                #region 1.限流拦截
                if (_rateLimiter.IsLimited(moduleName))
                {
                    string msg = $"【{moduleName}】模块触发并发限流,拒绝执行";
                    _logger.LogWarning("[{TraceId}][{Module}] {Msg}", auditTraceId, moduleName, msg);
                    auditRecord.Success = false;
                    auditRecord.ExceptionMessage = msg;
                    auditRecord.ResultJson = JsonSerializer.Serialize(JewelryBusinessResult.Fail(msg), _jsonOptions);
                    auditRecord.ElapsedMs = stopwatch.ElapsedMilliseconds;
                    await _auditRepository.SaveAuditRecordAsync(auditRecord);
                    return JewelryBusinessResult.Fail(msg);
                }
                #endregion

                #region 2.权限校验拦截
                if (!_permissionChecker.CheckPermission(context, permissionCode))
                {
                    string msg = $"操作员无[{permissionCode}]权限,禁止访问模块:{moduleName}";
                    _logger.LogWarning("[{TraceId}][{Module}] {Msg}", auditTraceId, moduleName, msg);
                    auditRecord.Success = false;
                    auditRecord.ExceptionMessage = msg;
                    auditRecord.ResultJson = JsonSerializer.Serialize(JewelryBusinessResult.Fail(msg), _jsonOptions);
                    auditRecord.ElapsedMs = stopwatch.ElapsedMilliseconds;
                    await _auditRepository.SaveAuditRecordAsync(auditRecord);
                    return JewelryBusinessResult.Fail(msg);
                }
                #endregion

                #region 3.执行业务
                _logger.LogInformation("[{TraceId}][{Module}]业务开始,单号:{OrderNo},入参:{Param}",
                    auditTraceId, moduleName, businessOrderNo, auditRecord.InputParamJson);

                var result = await _realService.ExecuteAsync(context, businessOrderNo, businessParam);

                stopwatch.Stop();
                auditRecord.ElapsedMs = stopwatch.ElapsedMilliseconds;
                auditRecord.Success = result.Success;
                auditRecord.ResultJson = JsonSerializer.Serialize(result, _jsonOptions);

                if (result.Success)
                {
                    _logger.LogInformation("[{TraceId}][{Module}]业务完成,单号:{OrderNo},耗时:{Ms}ms,信息:{Msg}",
                        auditTraceId, moduleName, businessOrderNo, stopwatch.ElapsedMilliseconds, result.Message);
                }
                else
                {
                    _logger.LogWarning("[{TraceId}][{Module}]业务执行失败,单号:{OrderNo},耗时:{Ms}ms,信息:{Msg}",
                        auditTraceId, moduleName, businessOrderNo, stopwatch.ElapsedMilliseconds, result.Message);
                }
                await _auditRepository.SaveAuditRecordAsync(auditRecord);
                return result;
                #endregion
            }
            catch (Exception ex)
            {
                stopwatch.Stop();
                _logger.LogError(ex, "[{TraceId}][{Module}]业务异常,单号:{OrderNo},耗时:{Ms}ms",
                    auditTraceId, moduleName, businessOrderNo, stopwatch.ElapsedMilliseconds);

                auditRecord.ElapsedMs = stopwatch.ElapsedMilliseconds;
                auditRecord.Success = false;
                auditRecord.ExceptionMessage = ex.ToString();
                auditRecord.ResultJson = JsonSerializer.Serialize(JewelryBusinessResult.Fail(ex.Message), _jsonOptions);
                await _auditRepository.SaveAuditRecordAsync(auditRecord);

                return JewelryBusinessResult.Fail($"模块[{moduleName}]运行异常:{ex.Message}");
            }
            finally
            {
                // 释放限流计数器
                _concurrentRateLimiter.Release(moduleName);
            }
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryBusinessFlowScheduler.cs
 */

using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Scheduler
{
    /// <summary>
    /// 珠宝全业务流程调度器
    /// 串联完整业务链路,支持手动调用与Hangfire任务调用
    /// </summary>
    public class JewelryBusinessFlowScheduler
    {
        private readonly IEnumerable<IJewelryBusinessService> _businessServices;
        private readonly ILogger<JewelryBusinessFlowScheduler> _logger;

        public JewelryBusinessFlowScheduler(IEnumerable<IJewelryBusinessService> businessServices, ILogger<JewelryBusinessFlowScheduler> logger)
        {
            _businessServices = businessServices;
            _logger = logger;
        }

        /// <summary>
        /// 顺序执行完整珠宝全业务流程
        /// </summary>
        public async Task RunFullBusinessFlowAsync(BusinessContext context, string orderNo, Dictionary<string, object> param)
        {
            _logger.LogInformation("[{TraceId}]==========开始执行珠宝全业务流程,单号:{OrderNo}==========", context.TraceId, orderNo);

            foreach (var service in _businessServices)
            {
                var result = await service.ExecuteAsync(context, orderNo, param);
                if (!result.Success)
                {
                    _logger.LogError("[{TraceId}]流程中断,模块:{Module},原因:{Msg}", context.TraceId, service.GetModuleName(), result.Message);
                    break;
                }
            }
            _logger.LogInformation("[{TraceId}]==========珠宝全业务流程执行结束,单号:{OrderNo}==========", context.TraceId, orderNo);
        }

        /// <summary>
        /// 高并发批量模拟多订单并行执行
        /// </summary>
        public async Task RunConcurrentBusinessAsync(BusinessContext baseContext, int orderCount)
        {
            List<Task> taskList = new();
            for (int i = 1; i <= orderCount; i++)
            {
                string orderNo = $"ORD-{DateTime.Now:yyyyMMdd}-{i:D6}";
                var ctx = new BusinessContext
                {
                    OperatorId = baseContext.OperatorId,
                    OperatorName = baseContext.OperatorName,
                    TenantId = baseContext.TenantId,
                    PermissionCodes = new HashSet<string>(baseContext.PermissionCodes)
                };
                var param = new Dictionary<string, object>
            {
                {"MaterialCode", "MAT-20260725-001"},
                {"ProductStyle", "铂金钻石戒指"},
                {"CustomerId", "CUS-89762"}
            };
                taskList.Add(RunFullBusinessFlowAsync(ctx, orderNo, param));
            }
            await Task.WhenAll(taskList);
            _logger.LogInformation("全部并发订单执行完成");
        }
    }
}

  

/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : BusinessSaleService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 业务销售业务服务(真实主体 RealSubject)
    /// </summary>
    public class BusinessSaleService : IJewelryBusinessService
    {
        private readonly ILogger<BusinessSaleService> _logger;

        public BusinessSaleService(ILogger<BusinessSaleService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "业务销售";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:SALE:ORDER";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(40, 130));
            _logger.LogDebug("[{TraceId}]客户洽谈、销售订单录入、会员档案建立", context.TraceId);

            if (!businessParam.ContainsKey("CustomerId"))
            {
                return JewelryBusinessResult.Fail("缺少客户编号,无法创建销售订单");
            }
            return JewelryBusinessResult.Ok("销售订单创建成功");
        }
    }
}



/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : FinanceService.cs
 */

using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 财务结算业务服务(真实主体 RealSubject)
    /// </summary>
    public class FinanceService : IJewelryBusinessService
    {
        private readonly ILogger<FinanceService> _logger;

        public FinanceService(ILogger<FinanceService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "财务结算";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:FINANCE:SETTLE";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(50, 150));
            _logger.LogDebug("[{TraceId}]成本核算、应收应付记账、票据单据生成", context.TraceId);

            return JewelryBusinessResult.Ok("财务单据生成完成,结算流程办结");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : HrAdminService.cs
 */


using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 人事行政业务服务(真实主体 RealSubject)
    /// </summary>
    public class HrAdminService : IJewelryBusinessService
    {
        private readonly ILogger<HrAdminService> _logger;

        public HrAdminService(ILogger<HrAdminService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "人事行政";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:HR:ADMIN";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(30, 90));
            _logger.LogDebug("[{TraceId}]员工考勤、入职离职办理、薪酬核算、行政采购管理", context.TraceId);

            return JewelryBusinessResult.Ok("人事行政流程办结");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : ItOperationService.cs
 */

using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// IT运维业务服务(真实主体 RealSubject)
    /// </summary>
    public class ItOperationService : IJewelryBusinessService
    {
        private readonly ILogger<ItOperationService> _logger;

        public ItOperationService(ILogger<ItOperationService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "IT运维";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:IT:OPS";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(20, 80));
            _logger.LogDebug("[{TraceId}]系统巡检、门店设备维护、账号权限调整", context.TraceId);

            return JewelryBusinessResult.Ok("IT运维工单处理完毕");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryDesignService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 珠宝设计制图业务服务(真实主体 RealSubject)
    /// </summary>
    public class JewelryDesignService : IJewelryBusinessService
    {
        private readonly ILogger<JewelryDesignService> _logger;

        public JewelryDesignService(ILogger<JewelryDesignService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "设计制图";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:DESIGN:EDIT";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(80, 200));
            _logger.LogDebug("[{TraceId}]根据客户需求生成珠宝3D图纸、渲染效果图", context.TraceId);

            if (!businessParam.ContainsKey("ProductStyle"))
            {
                return JewelryBusinessResult.Fail("缺少产品款式参数,无法开展设计制图");
            }
            return JewelryBusinessResult.Ok("珠宝设计图纸定稿,可下发生产");
        }
    }
}



/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryLogisticsService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 珠宝物流配送业务服务(真实主体 RealSubject)
    /// </summary>
    public class JewelryLogisticsService : IJewelryBusinessService
    {
        private readonly ILogger<JewelryLogisticsService> _logger;

        public JewelryLogisticsService(ILogger<JewelryLogisticsService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "物流配送";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:LOGISTICS:MANAGE";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(40, 120));
            _logger.LogDebug("[{TraceId}]保价物流下单、运单创建、物流跟踪绑定", context.TraceId);

            return JewelryBusinessResult.Ok("物流运单创建成功,商品出库配送");
        }
    }
}

/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryManufactureService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 珠宝加工生产业务服务(真实主体 RealSubject)
    /// </summary>
    public class JewelryManufactureService : IJewelryBusinessService
    {
        private readonly ILogger<JewelryManufactureService> _logger;

        public JewelryManufactureService(ILogger<JewelryManufactureService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "加工生产";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:MANUFACTURE:EXEC";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(100, 300));
            _logger.LogDebug("[{TraceId}]执行失蜡铸造、宝石镶嵌、抛光、电镀工序", context.TraceId);

            return JewelryBusinessResult.Ok("珠宝加工生产工序全部完成,等待质检");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryPackService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 珠宝包装业务服务(真实主体 RealSubject)
    /// </summary>
    public class JewelryPackService : IJewelryBusinessService
    {
        private readonly ILogger<JewelryPackService> _logger;

        public JewelryPackService(ILogger<JewelryPackService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "包装工序";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:PACK:OP";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(30, 100));
            _logger.LogDebug("[{TraceId}]礼盒装配、证书放置、防伪标签封装", context.TraceId);

            return JewelryBusinessResult.Ok("珠宝包装完成,待物流发货");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : JewelryQualityCheckService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 成品质检业务服务(真实主体 RealSubject)
    /// </summary>
    public class JewelryQualityCheckService : IJewelryBusinessService
    {
        private readonly ILogger<JewelryQualityCheckService> _logger;

        public JewelryQualityCheckService(ILogger<JewelryQualityCheckService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "成品质检";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:QC:CHECK";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(60, 180));
            _logger.LogDebug("[{TraceId}]尺寸校验、宝石牢固度、外观瑕疵、贵金属重量检测", context.TraceId);

            return JewelryBusinessResult.Ok("成品质检合格,允许进入包装流程");
        }
    }
}

/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : MarketingService.cs
 */

using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 营销推广业务服务(真实主体 RealSubject)
    /// </summary>
    public class MarketingService : IJewelryBusinessService
    {
        private readonly ILogger<MarketingService> _logger;

        public MarketingService(ILogger<MarketingService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "营销推广";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:MARKETING:PUBLISH";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(60, 160));
            _logger.LogDebug("[{TraceId}]新品宣传、会员优惠券推送、线上线下活动投放", context.TraceId);

            return JewelryBusinessResult.Ok("营销推广活动执行完成");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : RawMaterialPurchaseService.cs
 */
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 原料采购核验业务服务(真实主体 RealSubject)
    /// </summary>
    public class RawMaterialPurchaseService : IJewelryBusinessService
    {
        private readonly ILogger<RawMaterialPurchaseService> _logger;

        public RawMaterialPurchaseService(ILogger<RawMaterialPurchaseService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "原料采购核验";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:RAW_MATERIAL:PURCHASE";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(50, 150));
            _logger.LogDebug("[{TraceId}]原料入库核验:贵金属纯度、宝石证书查验", context.TraceId);

            if (!businessParam.ContainsKey("MaterialCode"))
            {
                return JewelryBusinessResult.Fail("缺少原料编码,采购核验不通过");
            }
            return JewelryBusinessResult.Ok("原料采购核验完成,准予入库");
        }
    }
}


/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : StaffTrainService.cs
 */


using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.Text;

namespace ProxyPattern.Services
{
    /// <summary>
    /// 员工培训业务服务(真实主体 RealSubject)
    /// </summary>
    public class StaffTrainService : IJewelryBusinessService
    {
        private readonly ILogger<StaffTrainService> _logger;

        public StaffTrainService(ILogger<StaffTrainService> logger)
        {
            _logger = logger;
        }

        public string GetModuleName()
        {
            return "员工培训";
        }

        public string GetRequiredPermissionCode()
        {
            return "JEWELRY:TRAIN:MANAGE";
        }

        public async Task<JewelryBusinessResult> ExecuteAsync(BusinessContext context, string businessOrderNo, Dictionary<string, object> businessParam)
        {
            await Task.Delay(Random.Shared.Next(50, 140));
            _logger.LogDebug("[{TraceId}]珠宝专业知识、销售话术、质检标准培训任务执行", context.TraceId);

            return JewelryBusinessResult.Ok("员工培训任务完成登记");
        }
    }
}

 

调用:

/**
# encoding: utf-8 
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:结构型模式 Structural Patterns  代理模式Proxy 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/12 22:16 
# User      :  geovindu
# Product   : Visual Studio 2026
# Project   : CSharpDesignPattern
# File      : ProxyBll.cs
 */


using Hangfire;
using Hangfire.MemoryStorage;
using Karambolo.Extensions.Logging.File;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using ProxyPattern.Domain.Abstractions;
using ProxyPattern.Infrastructure.Audit;
using ProxyPattern.Infrastructure.Hangfire;
using ProxyPattern.Infrastructure.Logging;
using ProxyPattern.Infrastructure.RateLimit;
using ProxyPattern.Infrastructure.Security;
using ProxyPattern.Proxy;
using ProxyPattern.Scheduler;
using ProxyPattern.Services;
using ProxyPattern.Domain.Models;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Text.Json;


namespace BLL
{


    public class ProxyBll
    {

        /// <summary>
        /// 统一注册业务代理
        /// </summary>
        private static void RegisterBusinessProxy<TReal>(IServiceCollection services)
            where TReal : class, IJewelryBusinessService
        {
            services.AddTransient<IJewelryBusinessService, JewelryBusinessServiceProxy<TReal>>(sp =>
            {
                var real = sp.GetRequiredService<TReal>();
                var logger = sp.GetRequiredService<ILogger<JewelryBusinessServiceProxy<TReal>>>();
                var permChecker = sp.GetRequiredService<IPermissionChecker>();
                var rateLimiter = sp.GetRequiredService<IRateLimiter>();
                var auditRepo = sp.GetRequiredService<IAuditRepository>();
                var concurrentLimiter = sp.GetRequiredService<ConcurrentRateLimiter>();
                return new JewelryBusinessServiceProxy<TReal>(real, logger, permChecker, rateLimiter, auditRepo, concurrentLimiter);
            });
        }
        /// <summary>
        /// 
        /// </summary>
        public async void Demo()
        {
            Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
            const string LogBasePath = "Logs";
            const int LogRetainDays = 30;

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

    loggingBuilder.AddFile(fileBuilder =>
                    {
                        fileBuilder.RootPath = Directory.GetCurrentDirectory();
                        string todayDate = DateTime.Now.ToString("yyyy-MM-dd");
                        fileBuilder.Files = new[]
                        {
                            new LogFileOptions { Path = $"{LogBasePath}/{todayDate}/app-debug.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Debug } },
                            new LogFileOptions { Path = $"{LogBasePath}/{todayDate}/app-info.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Information } },
                            new LogFileOptions { Path = $"{LogBasePath}/{todayDate}/app-warn.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Warning } },
                            new LogFileOptions { Path = $"{LogBasePath}/{todayDate}/app-error.log", MinLevel = new Dictionary<string, LogLevel> { [""] = LogLevel.Error } }
                        };
                    });
                    loggingBuilder.SetMinimumLevel(LogLevel.Debug);
                })
                .ConfigureServices((ctx, services) =>
                {
                    #region 基础设施注册
                    services.AddSingleton<IPermissionChecker, JewelryPermissionChecker>();
                    services.AddSingleton<IAuditRepository, MemoryAuditRepository>();
                    services.AddSingleton<ConcurrentRateLimiter>(_ => new ConcurrentRateLimiter(20));
                    services.AddSingleton<IRateLimiter>(sp => sp.GetRequiredService<ConcurrentRateLimiter>());

                    // 日志清理后台服务
                    services.AddHostedService(sp =>
                        new LogCleanBackgroundService(sp.GetRequiredService<ILogger<LogCleanBackgroundService>>(),
                            LogBasePath, LogRetainDays));

                    // Hangfire 内存存储
                    services.AddHangfire(config =>
                    {
                        config.SetDataCompatibilityLevel(CompatibilityLevel.Version_180);
                        config.UseMemoryStorage();
                    });
                    services.AddHangfireServer();
                    services.AddTransient<HangfireTaskScheduler>();
                    #endregion

                    #region 注册真实业务服务
                    services.AddTransient<RawMaterialPurchaseService>();
                    services.AddTransient<JewelryDesignService>();
                    services.AddTransient<JewelryManufactureService>();
                    services.AddTransient<JewelryQualityCheckService>();
                    services.AddTransient<JewelryPackService>();
                    services.AddTransient<JewelryLogisticsService>();
                    services.AddTransient<FinanceService>();
                    services.AddTransient<MarketingService>();
                    services.AddTransient<BusinessSaleService>();
                    services.AddTransient<HrAdminService>();
                    services.AddTransient<ItOperationService>();
                    services.AddTransient<StaffTrainService>();
                    #endregion

                    #region 代理模式注册工厂方法
                    RegisterBusinessProxy<RawMaterialPurchaseService>(services);
                    RegisterBusinessProxy<JewelryDesignService>(services);
                    RegisterBusinessProxy<JewelryManufactureService>(services);
                    RegisterBusinessProxy<JewelryQualityCheckService>(services);
                    RegisterBusinessProxy<JewelryPackService>(services);
                    RegisterBusinessProxy<JewelryLogisticsService>(services);
                    RegisterBusinessProxy<FinanceService>(services);
                    RegisterBusinessProxy<MarketingService>(services);
                    RegisterBusinessProxy<BusinessSaleService>(services);
                    RegisterBusinessProxy<HrAdminService>(services);
                    RegisterBusinessProxy<ItOperationService>(services);
                    RegisterBusinessProxy<StaffTrainService>(services);
                    #endregion

                    services.AddTransient<JewelryBusinessFlowScheduler>();
                })
                .Build();

            // 测试上下文
            var testContext = new BusinessContext
            {
                OperatorId = "OP001",
                OperatorName = "珠宝管理员",
                TenantId = "T001",
                PermissionCodes = new HashSet<string>
            {
                "JEWELRY:RAW_MATERIAL:PURCHASE",
                "JEWELRY:DESIGN:EDIT",
                "JEWELRY:MANUFACTURE:EXEC",
                "JEWELRY:QC:CHECK",
                "JEWELRY:PACK:OP",
                "JEWELRY:LOGISTICS:MANAGE",
                "JEWELRY:FINANCE:SETTLE",
                "JEWELRY:MARKETING:PUBLISH",
                "JEWELRY:SALE:ORDER",
                "JEWELRY:HR:ADMIN",
                "JEWELRY:IT:OPS",
                "JEWELRY:TRAIN:MANAGE"
            }
            };

            var scheduler = host.Services.GetRequiredService<JewelryBusinessFlowScheduler>();
            var hangfireScheduler = host.Services.GetRequiredService<HangfireTaskScheduler>();

            Console.WriteLine("=====启动并发业务测试=====");
            await scheduler.RunConcurrentBusinessAsync(testContext, 5);

            // 演示Hangfire一次性任务入队
            hangfireScheduler.EnqueueBusinessTask(testContext, "HANG-ORD-001", new Dictionary<string, object>
        {
            {"MaterialCode", "MAT-HF-001"}
        });

            Console.WriteLine("执行完成,按任意键退出");
            Console.ReadKey();
            await host.StopAsync();
        }
    }
}

  

输出:

image

 

posted @ 2026-07-27 22:42  ®Geovin Du Dream Park™  阅读(10)  评论(0)    收藏  举报